summaryrefslogtreecommitdiff
path: root/spec/rubyspec/core/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'spec/rubyspec/core/kernel')
-rw-r--r--spec/rubyspec/core/kernel/Array_spec.rb97
-rw-r--r--spec/rubyspec/core/kernel/Complex_spec.rb6
-rw-r--r--spec/rubyspec/core/kernel/Float_spec.rb316
-rw-r--r--spec/rubyspec/core/kernel/Hash_spec.rb57
-rw-r--r--spec/rubyspec/core/kernel/Integer_spec.rb697
-rw-r--r--spec/rubyspec/core/kernel/Rational_spec.rb6
-rw-r--r--spec/rubyspec/core/kernel/String_spec.rb106
-rw-r--r--spec/rubyspec/core/kernel/__callee___spec.rb48
-rw-r--r--spec/rubyspec/core/kernel/__dir___spec.rb13
-rw-r--r--spec/rubyspec/core/kernel/__method___spec.rb40
-rw-r--r--spec/rubyspec/core/kernel/abort_spec.rb15
-rw-r--r--spec/rubyspec/core/kernel/at_exit_spec.rb44
-rw-r--r--spec/rubyspec/core/kernel/autoload_spec.rb122
-rw-r--r--spec/rubyspec/core/kernel/backtick_spec.rb80
-rw-r--r--spec/rubyspec/core/kernel/binding_spec.rb51
-rw-r--r--spec/rubyspec/core/kernel/block_given_spec.rb38
-rw-r--r--spec/rubyspec/core/kernel/caller_locations_spec.rb32
-rw-r--r--spec/rubyspec/core/kernel/caller_spec.rb31
-rw-r--r--spec/rubyspec/core/kernel/case_compare_spec.rb135
-rw-r--r--spec/rubyspec/core/kernel/catch_spec.rb127
-rw-r--r--spec/rubyspec/core/kernel/chomp_spec.rb67
-rw-r--r--spec/rubyspec/core/kernel/chop_spec.rb55
-rw-r--r--spec/rubyspec/core/kernel/class_spec.rb26
-rw-r--r--spec/rubyspec/core/kernel/clone_spec.rb108
-rw-r--r--spec/rubyspec/core/kernel/comparison_spec.rb31
-rw-r--r--spec/rubyspec/core/kernel/define_singleton_method_spec.rb101
-rw-r--r--spec/rubyspec/core/kernel/display_spec.rb6
-rw-r--r--spec/rubyspec/core/kernel/dup_spec.rb67
-rw-r--r--spec/rubyspec/core/kernel/enum_for_spec.rb5
-rw-r--r--spec/rubyspec/core/kernel/eql_spec.rb11
-rw-r--r--spec/rubyspec/core/kernel/equal_value_spec.rb15
-rw-r--r--spec/rubyspec/core/kernel/eval_spec.rb216
-rw-r--r--spec/rubyspec/core/kernel/exec_spec.rb18
-rw-r--r--spec/rubyspec/core/kernel/exit_spec.rb27
-rw-r--r--spec/rubyspec/core/kernel/extend_spec.rb79
-rw-r--r--spec/rubyspec/core/kernel/fail_spec.rb43
-rw-r--r--spec/rubyspec/core/kernel/fixtures/__callee__.rb34
-rw-r--r--spec/rubyspec/core/kernel/fixtures/__method__.rb34
-rw-r--r--spec/rubyspec/core/kernel/fixtures/autoload_b.rb5
-rw-r--r--spec/rubyspec/core/kernel/fixtures/autoload_c.rb5
-rw-r--r--spec/rubyspec/core/kernel/fixtures/autoload_d.rb5
-rw-r--r--spec/rubyspec/core/kernel/fixtures/autoload_frozen.rb7
-rw-r--r--spec/rubyspec/core/kernel/fixtures/caller.rb7
-rw-r--r--spec/rubyspec/core/kernel/fixtures/caller_locations.rb7
-rw-r--r--spec/rubyspec/core/kernel/fixtures/chomp.rb4
-rw-r--r--spec/rubyspec/core/kernel/fixtures/chomp_f.rb4
-rw-r--r--spec/rubyspec/core/kernel/fixtures/chop.rb4
-rw-r--r--spec/rubyspec/core/kernel/fixtures/chop_f.rb4
-rw-r--r--spec/rubyspec/core/kernel/fixtures/classes.rb425
-rw-r--r--spec/rubyspec/core/kernel/fixtures/eval_locals.rb6
-rw-r--r--spec/rubyspec/core/kernel/fixtures/eval_return_with_lambda.rb12
-rw-r--r--spec/rubyspec/core/kernel/fixtures/eval_return_without_lambda.rb14
-rw-r--r--spec/rubyspec/core/kernel/fixtures/test.rb362
-rw-r--r--spec/rubyspec/core/kernel/fork_spec.rb15
-rw-r--r--spec/rubyspec/core/kernel/format_spec.rb14
-rw-r--r--spec/rubyspec/core/kernel/freeze_spec.rb67
-rw-r--r--spec/rubyspec/core/kernel/frozen_spec.rb52
-rw-r--r--spec/rubyspec/core/kernel/gets_spec.rb12
-rw-r--r--spec/rubyspec/core/kernel/global_variables_spec.rb26
-rw-r--r--spec/rubyspec/core/kernel/gsub_spec.rb96
-rw-r--r--spec/rubyspec/core/kernel/inspect_spec.rb31
-rw-r--r--spec/rubyspec/core/kernel/instance_of_spec.rb40
-rw-r--r--spec/rubyspec/core/kernel/instance_variable_defined_spec.rb41
-rw-r--r--spec/rubyspec/core/kernel/instance_variable_get_spec.rb105
-rw-r--r--spec/rubyspec/core/kernel/instance_variable_set_spec.rb93
-rw-r--r--spec/rubyspec/core/kernel/instance_variables_spec.rb27
-rw-r--r--spec/rubyspec/core/kernel/is_a_spec.rb6
-rw-r--r--spec/rubyspec/core/kernel/iterator_spec.rb12
-rw-r--r--spec/rubyspec/core/kernel/itself_spec.rb10
-rw-r--r--spec/rubyspec/core/kernel/kind_of_spec.rb6
-rw-r--r--spec/rubyspec/core/kernel/lambda_spec.rb86
-rw-r--r--spec/rubyspec/core/kernel/load_spec.rb40
-rw-r--r--spec/rubyspec/core/kernel/local_variables_spec.rb37
-rw-r--r--spec/rubyspec/core/kernel/loop_spec.rb81
-rw-r--r--spec/rubyspec/core/kernel/match_spec.rb14
-rw-r--r--spec/rubyspec/core/kernel/method_spec.rb37
-rw-r--r--spec/rubyspec/core/kernel/methods_spec.rb101
-rw-r--r--spec/rubyspec/core/kernel/nil_spec.rb6
-rw-r--r--spec/rubyspec/core/kernel/not_match_spec.rb21
-rw-r--r--spec/rubyspec/core/kernel/object_id_spec.rb6
-rw-r--r--spec/rubyspec/core/kernel/open_spec.rb141
-rw-r--r--spec/rubyspec/core/kernel/p_spec.rb79
-rw-r--r--spec/rubyspec/core/kernel/print_spec.rb12
-rw-r--r--spec/rubyspec/core/kernel/printf_spec.rb34
-rw-r--r--spec/rubyspec/core/kernel/private_methods_spec.rb69
-rw-r--r--spec/rubyspec/core/kernel/proc_spec.rb50
-rw-r--r--spec/rubyspec/core/kernel/protected_methods_spec.rb69
-rw-r--r--spec/rubyspec/core/kernel/public_method_spec.rb32
-rw-r--r--spec/rubyspec/core/kernel/public_methods_spec.rb76
-rw-r--r--spec/rubyspec/core/kernel/public_send_spec.rb108
-rw-r--r--spec/rubyspec/core/kernel/putc_spec.rb39
-rw-r--r--spec/rubyspec/core/kernel/puts_spec.rb29
-rw-r--r--spec/rubyspec/core/kernel/raise_spec.rb17
-rw-r--r--spec/rubyspec/core/kernel/rand_spec.rb139
-rw-r--r--spec/rubyspec/core/kernel/readline_spec.rb12
-rw-r--r--spec/rubyspec/core/kernel/readlines_spec.rb12
-rw-r--r--spec/rubyspec/core/kernel/remove_instance_variable_spec.rb59
-rw-r--r--spec/rubyspec/core/kernel/require_relative_spec.rb349
-rw-r--r--spec/rubyspec/core/kernel/require_spec.rb36
-rw-r--r--spec/rubyspec/core/kernel/respond_to_missing_spec.rb100
-rw-r--r--spec/rubyspec/core/kernel/respond_to_spec.rb73
-rw-r--r--spec/rubyspec/core/kernel/select_spec.rb20
-rw-r--r--spec/rubyspec/core/kernel/send_spec.rb68
-rw-r--r--spec/rubyspec/core/kernel/set_trace_func_spec.rb12
-rw-r--r--spec/rubyspec/core/kernel/shared/dup_clone.rb125
-rw-r--r--spec/rubyspec/core/kernel/shared/kind_of.rb44
-rw-r--r--spec/rubyspec/core/kernel/shared/lambda.rb9
-rw-r--r--spec/rubyspec/core/kernel/shared/load.rb139
-rw-r--r--spec/rubyspec/core/kernel/shared/method.rb50
-rw-r--r--spec/rubyspec/core/kernel/shared/require.rb703
-rw-r--r--spec/rubyspec/core/kernel/singleton_class_spec.rb27
-rw-r--r--spec/rubyspec/core/kernel/singleton_methods_spec.rb180
-rw-r--r--spec/rubyspec/core/kernel/sleep_spec.rb52
-rw-r--r--spec/rubyspec/core/kernel/spawn_spec.rb25
-rw-r--r--spec/rubyspec/core/kernel/sprintf_spec.rb310
-rw-r--r--spec/rubyspec/core/kernel/srand_spec.rb61
-rw-r--r--spec/rubyspec/core/kernel/sub_spec.rb26
-rw-r--r--spec/rubyspec/core/kernel/syscall_spec.rb12
-rw-r--r--spec/rubyspec/core/kernel/system_spec.rb107
-rw-r--r--spec/rubyspec/core/kernel/taint_spec.rb45
-rw-r--r--spec/rubyspec/core/kernel/tainted_spec.rb12
-rw-r--r--spec/rubyspec/core/kernel/tap_spec.rb13
-rw-r--r--spec/rubyspec/core/kernel/test_spec.rb98
-rw-r--r--spec/rubyspec/core/kernel/throw_spec.rb80
-rw-r--r--spec/rubyspec/core/kernel/to_enum_spec.rb5
-rw-r--r--spec/rubyspec/core/kernel/to_s_spec.rb16
-rw-r--r--spec/rubyspec/core/kernel/trace_var_spec.rb54
-rw-r--r--spec/rubyspec/core/kernel/trap_spec.rb12
-rw-r--r--spec/rubyspec/core/kernel/trust_spec.rb25
-rw-r--r--spec/rubyspec/core/kernel/untaint_spec.rb25
-rw-r--r--spec/rubyspec/core/kernel/untrace_var_spec.rb12
-rw-r--r--spec/rubyspec/core/kernel/untrust_spec.rb25
-rw-r--r--spec/rubyspec/core/kernel/untrusted_spec.rb28
-rw-r--r--spec/rubyspec/core/kernel/warn_spec.rb79
134 files changed, 8991 insertions, 0 deletions
diff --git a/spec/rubyspec/core/kernel/Array_spec.rb b/spec/rubyspec/core/kernel/Array_spec.rb
new file mode 100644
index 0000000000..6031a828f6
--- /dev/null
+++ b/spec/rubyspec/core/kernel/Array_spec.rb
@@ -0,0 +1,97 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel" do
+ it "has private instance method Array()" do
+ Kernel.should have_private_instance_method(:Array)
+ end
+end
+
+describe :kernel_Array, shared: true do
+ before :each do
+ @array = [1, 2, 3]
+ end
+
+ it "does not call #to_ary on an Array" do
+ @array.should_not_receive(:to_ary)
+ @object.send(@method, @array).should == @array
+ end
+
+ it "calls #to_ary to convert the argument to an Array" do
+ obj = mock("Array([1,2,3])")
+ obj.should_receive(:to_ary).and_return(@array)
+ obj.should_not_receive(:to_a)
+
+ @object.send(@method, obj).should == @array
+ end
+
+ it "does not call #to_a on an Array" do
+ @array.should_not_receive(:to_a)
+ @object.send(@method, @array).should == @array
+ end
+
+ it "calls #to_a if the argument does not respond to #to_ary" do
+ obj = mock("Array([1,2,3])")
+ obj.should_receive(:to_a).and_return(@array)
+
+ @object.send(@method, obj).should == @array
+ end
+
+ it "calls #to_a if #to_ary returns nil" do
+ obj = mock("Array([1,2,3])")
+ obj.should_receive(:to_ary).and_return(nil)
+ obj.should_receive(:to_a).and_return(@array)
+
+ @object.send(@method, obj).should == @array
+ end
+
+ it "returns an Array containing the argument if #to_a returns nil" do
+ obj = mock("Array([1,2,3])")
+ obj.should_receive(:to_a).and_return(nil)
+
+ @object.send(@method, obj).should == [obj]
+ end
+
+ it "calls #to_ary first, even if it's private" do
+ obj = KernelSpecs::PrivateToAry.new
+
+ @object.send(@method, obj).should == [1, 2]
+ end
+
+ it "calls #to_a if #to_ary is not defined, even if it's private" do
+ obj = KernelSpecs::PrivateToA.new
+
+ @object.send(@method, obj).should == [3, 4]
+ end
+
+ it "returns an Array containing the argument if it responds to neither #to_ary nor #to_a" do
+ obj = mock("Array(x)")
+ @object.send(@method, obj).should == [obj]
+ end
+
+ it "returns an empty Array when passed nil" do
+ @object.send(@method, nil).should == []
+ end
+
+ it "raises a TypeError if #to_ary does not return an Array" do
+ obj = mock("Array() string")
+ obj.should_receive(:to_ary).and_return("string")
+
+ lambda { @object.send(@method, obj) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if #to_a does not return an Array" do
+ obj = mock("Array() string")
+ obj.should_receive(:to_a).and_return("string")
+
+ lambda { @object.send(@method, obj) }.should raise_error(TypeError)
+ end
+end
+
+describe "Kernel.Array" do
+ it_behaves_like :kernel_Array, :Array_method, KernelSpecs
+end
+
+describe "Kernel#Array" do
+ it_behaves_like :kernel_Array, :Array_function, KernelSpecs
+end
diff --git a/spec/rubyspec/core/kernel/Complex_spec.rb b/spec/rubyspec/core/kernel/Complex_spec.rb
new file mode 100644
index 0000000000..b156cc4549
--- /dev/null
+++ b/spec/rubyspec/core/kernel/Complex_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../../../shared/complex/Complex', __FILE__)
+
+describe "Kernel.Complex()" do
+ it_behaves_like :kernel_Complex, :Complex
+end
diff --git a/spec/rubyspec/core/kernel/Float_spec.rb b/spec/rubyspec/core/kernel/Float_spec.rb
new file mode 100644
index 0000000000..ee20190094
--- /dev/null
+++ b/spec/rubyspec/core/kernel/Float_spec.rb
@@ -0,0 +1,316 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe :kernel_float, shared: true do
+ it "returns the identical Float for numeric Floats" do
+ float = 1.12
+ float2 = @object.send(:Float, float)
+ float2.should == float
+ float2.object_id.should == float.object_id
+ end
+
+ it "returns a Float for Fixnums" do
+ @object.send(:Float, 1).should == 1.0
+ end
+
+ it "returns a Float for Complex with only a real part" do
+ @object.send(:Float, Complex(1)).should == 1.0
+ end
+
+ it "returns a Float for Bignums" do
+ @object.send(:Float, 1000000000000).should == 1000000000000.0
+ end
+
+ it "raises an ArgumentError for nil" do
+ lambda { @object.send(:Float, nil) }.should raise_error(TypeError)
+ end
+
+ it "returns the identical NaN for NaN" do
+ nan = nan_value
+ nan.nan?.should be_true
+ nan2 = @object.send(:Float, nan)
+ nan2.nan?.should be_true
+ nan2.should equal(nan)
+ end
+
+ it "returns the same Infinity for Infinity" do
+ infinity = infinity_value
+ infinity2 = @object.send(:Float, infinity)
+ infinity2.should == infinity_value
+ infinity.should equal(infinity2)
+ end
+
+ it "converts Strings to floats without calling #to_f" do
+ string = "10"
+ string.should_not_receive(:to_f)
+ @object.send(:Float, string).should == 10.0
+ end
+
+ it "converts Strings with decimal points into Floats" do
+ @object.send(:Float, "10.0").should == 10.0
+ end
+
+ it "raises an ArgumentError for a String of word characters" do
+ lambda { @object.send(:Float, "float") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if there are two decimal points in the String" do
+ lambda { @object.send(:Float, "10.0.0") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError for a String of numbers followed by word characters" do
+ lambda { @object.send(:Float, "10D") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError for a String of word characters followed by numbers" do
+ lambda { @object.send(:Float, "D10") }.should raise_error(ArgumentError)
+ end
+
+ it "is strict about the string form even across newlines" do
+ lambda { @object.send(:Float, "not a number\n10") }.should raise_error(ArgumentError)
+ lambda { @object.send(:Float, "10\nnot a number") }.should raise_error(ArgumentError)
+ end
+
+ it "converts String subclasses to floats without calling #to_f" do
+ my_string = Class.new(String) do
+ def to_f() 1.2 end
+ end
+
+ @object.send(:Float, my_string.new("10")).should == 10.0
+ end
+
+ it "returns a positive Float if the string is prefixed with +" do
+ @object.send(:Float, "+10").should == 10.0
+ @object.send(:Float, " +10").should == 10.0
+ end
+
+ it "returns a negative Float if the string is prefixed with +" do
+ @object.send(:Float, "-10").should == -10.0
+ @object.send(:Float, " -10").should == -10.0
+ end
+
+ it "raises an ArgumentError if a + or - is embedded in a String" do
+ lambda { @object.send(:Float, "1+1") }.should raise_error(ArgumentError)
+ lambda { @object.send(:Float, "1-1") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if a String has a trailing + or -" do
+ lambda { @object.send(:Float, "11+") }.should raise_error(ArgumentError)
+ lambda { @object.send(:Float, "11-") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError for a String with a leading _" do
+ lambda { @object.send(:Float, "_1") }.should raise_error(ArgumentError)
+ end
+
+ it "returns a value for a String with an embedded _" do
+ @object.send(:Float, "1_000").should == 1000.0
+ end
+
+ it "raises an ArgumentError for a String with a trailing _" do
+ lambda { @object.send(:Float, "10_") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError for a String of \\0" do
+ lambda { @object.send(:Float, "\0") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError for a String with a leading \\0" do
+ lambda { @object.send(:Float, "\01") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError for a String with an embedded \\0" do
+ lambda { @object.send(:Float, "1\01") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError for a String with a trailing \\0" do
+ lambda { @object.send(:Float, "1\0") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError for a String that is just an empty space" do
+ lambda { @object.send(:Float, " ") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError for a String that with an embedded space" do
+ lambda { @object.send(:Float, "1 2") }.should raise_error(ArgumentError)
+ end
+
+ it "returns a value for a String with a leading space" do
+ @object.send(:Float, " 1").should == 1.0
+ end
+
+ it "returns a value for a String with a trailing space" do
+ @object.send(:Float, "1 ").should == 1.0
+ end
+
+ it "returns a value for a String with any leading whitespace" do
+ @object.send(:Float, "\t\n1").should == 1.0
+ end
+
+ it "returns a value for a String with any trailing whitespace" do
+ @object.send(:Float, "1\t\n").should == 1.0
+ end
+
+ %w(e E).each do |e|
+ it "raises an ArgumentError if #{e} is the trailing character" do
+ lambda { @object.send(:Float, "2#{e}") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if #{e} is the leading character" do
+ lambda { @object.send(:Float, "#{e}2") }.should raise_error(ArgumentError)
+ end
+
+ it "returns Infinity for '2#{e}1000'" do
+ @object.send(:Float, "2#{e}1000").should == Float::INFINITY
+ end
+
+ it "returns 0 for '2#{e}-1000'" do
+ @object.send(:Float, "2#{e}-1000").should == 0
+ end
+
+ it "allows embedded _ in a number on either side of the #{e}" do
+ @object.send(:Float, "2_0#{e}100").should == 20e100
+ @object.send(:Float, "20#{e}1_00").should == 20e100
+ @object.send(:Float, "2_0#{e}1_00").should == 20e100
+ end
+
+ it "raises an exception if a space is embedded on either side of the '#{e}'" do
+ lambda { @object.send(:Float, "2 0#{e}100") }.should raise_error(ArgumentError)
+ lambda { @object.send(:Float, "20#{e}1 00") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an exception if there's a leading _ on either side of the '#{e}'" do
+ lambda { @object.send(:Float, "_20#{e}100") }.should raise_error(ArgumentError)
+ lambda { @object.send(:Float, "20#{e}_100") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an exception if there's a trailing _ on either side of the '#{e}'" do
+ lambda { @object.send(:Float, "20_#{e}100") }.should raise_error(ArgumentError)
+ lambda { @object.send(:Float, "20#{e}100_") }.should raise_error(ArgumentError)
+ end
+
+ it "allows decimal points on the left side of the '#{e}'" do
+ @object.send(:Float, "2.0#{e}2").should == 2e2
+ end
+
+ it "raises an ArgumentError if there's a decimal point on the right side of the '#{e}'" do
+ lambda { @object.send(:Float, "20#{e}2.0") }.should raise_error(ArgumentError)
+ end
+ end
+
+ describe "for hexadecimal literals with binary exponent" do
+ %w(p P).each do |p|
+ it "interprets the fractional part (on the left side of '#{p}') in hexadecimal" do
+ @object.send(:Float, "0x10#{p}0").should == 16.0
+ end
+
+ it "interprets the exponent (on the right of '#{p}') in decimal" do
+ @object.send(:Float, "0x1#{p}10").should == 1024.0
+ end
+
+ it "raises an ArgumentError if #{p} is the trailing character" do
+ lambda { @object.send(:Float, "0x1#{p}") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if #{p} is the leading character" do
+ lambda { @object.send(:Float, "0x#{p}1") }.should raise_error(ArgumentError)
+ end
+
+ it "returns Infinity for '0x1#{p}10000'" do
+ @object.send(:Float, "0x1#{p}10000").should == Float::INFINITY
+ end
+
+ it "returns 0 for '0x1#{p}-10000'" do
+ @object.send(:Float, "0x1#{p}-10000").should == 0
+ end
+
+ it "allows embedded _ in a number on either side of the #{p}" do
+ @object.send(:Float, "0x1_0#{p}10").should == 16384.0
+ @object.send(:Float, "0x10#{p}1_0").should == 16384.0
+ @object.send(:Float, "0x1_0#{p}1_0").should == 16384.0
+ end
+
+ it "raises an exception if a space is embedded on either side of the '#{p}'" do
+ lambda { @object.send(:Float, "0x1 0#{p}10") }.should raise_error(ArgumentError)
+ lambda { @object.send(:Float, "0x10#{p}1 0") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an exception if there's a leading _ on either side of the '#{p}'" do
+ lambda { @object.send(:Float, "0x_10#{p}10") }.should raise_error(ArgumentError)
+ lambda { @object.send(:Float, "0x10#{p}_10") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an exception if there's a trailing _ on either side of the '#{p}'" do
+ lambda { @object.send(:Float, "0x10_#{p}10") }.should raise_error(ArgumentError)
+ lambda { @object.send(:Float, "0x10#{p}10_") }.should raise_error(ArgumentError)
+ end
+
+ it "allows hexadecimal points on the left side of the '#{p}'" do
+ @object.send(:Float, "0x1.8#{p}0").should == 1.5
+ end
+
+ it "raises an ArgumentError if there's a decimal point on the right side of the '#{p}'" do
+ lambda { @object.send(:Float, "0x1#{p}1.0") }.should raise_error(ArgumentError)
+ end
+ end
+ end
+
+ it "returns a Float that can be a parameter to #Float again" do
+ float = @object.send(:Float, "10")
+ @object.send(:Float, float).should == 10.0
+ end
+
+ it "otherwise, converts the given argument to a Float by calling #to_f" do
+ (obj = mock('1.2')).should_receive(:to_f).once.and_return(1.2)
+ obj.should_not_receive(:to_i)
+ @object.send(:Float, obj).should == 1.2
+ end
+
+ it "returns the identical NaN if to_f is called and it returns NaN" do
+ nan = nan_value
+ (nan_to_f = mock('NaN')).should_receive(:to_f).once.and_return(nan)
+ nan2 = @object.send(:Float, nan_to_f)
+ nan2.nan?.should be_true
+ nan2.should equal(nan)
+ end
+
+ it "returns the identical Infinity if to_f is called and it returns Infinity" do
+ infinity = infinity_value
+ (infinity_to_f = mock('Infinity')).should_receive(:to_f).once.and_return(infinity)
+ infinity2 = @object.send(:Float, infinity_to_f)
+ infinity2.should equal(infinity)
+ end
+
+ it "raises a TypeError if #to_f is not provided" do
+ lambda { @object.send(:Float, mock('x')) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if #to_f returns a String" do
+ (obj = mock('ha!')).should_receive(:to_f).once.and_return('ha!')
+ lambda { @object.send(:Float, obj) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if #to_f returns an Integer" do
+ (obj = mock('123')).should_receive(:to_f).once.and_return(123)
+ lambda { @object.send(:Float, obj) }.should raise_error(TypeError)
+ end
+
+ it "raises a RangeError when passed a Complex argument" do
+ c = Complex(2, 3)
+ lambda { @object.send(:Float, c) }.should raise_error(RangeError)
+ end
+end
+
+describe "Kernel.Float" do
+ it_behaves_like :kernel_float, :Float, Kernel
+end
+
+describe "Kernel#Float" do
+ it_behaves_like :kernel_float, :Float, Object.new
+end
+
+describe "Kernel#Float" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:Float)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/Hash_spec.rb b/spec/rubyspec/core/kernel/Hash_spec.rb
new file mode 100644
index 0000000000..8d51316c75
--- /dev/null
+++ b/spec/rubyspec/core/kernel/Hash_spec.rb
@@ -0,0 +1,57 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#hash" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "Kernel" do
+ it "has private instance method Hash()" do
+ Kernel.should have_private_instance_method(:Hash)
+ end
+end
+
+describe :kernel_Hash, shared: true do
+ before :each do
+ @hash = { a: 1}
+ end
+
+ it "converts nil to a Hash" do
+ @object.send(@method, nil).should == {}
+ end
+
+ it "converts an empty array to a Hash" do
+ @object.send(@method, []).should == {}
+ end
+
+ it "does not call #to_hash on an Hash" do
+ @hash.should_not_receive(:to_hash)
+ @object.send(@method, @hash).should == @hash
+ end
+
+ it "calls #to_hash to convert the argument to an Hash" do
+ obj = mock("Hash(a: 1)")
+ obj.should_receive(:to_hash).and_return(@hash)
+
+ @object.send(@method, obj).should == @hash
+ end
+
+ it "raises a TypeError if it doesn't respond to #to_hash" do
+ lambda { @object.send(@method, mock("")) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if #to_hash does not return an Hash" do
+ obj = mock("Hash() string")
+ obj.should_receive(:to_hash).and_return("string")
+
+ lambda { @object.send(@method, obj) }.should raise_error(TypeError)
+ end
+end
+
+describe "Kernel.Hash" do
+ it_behaves_like :kernel_Hash, :Hash_method, KernelSpecs
+end
+
+describe "Kernel#Hash" do
+ it_behaves_like :kernel_Hash, :Hash_function, KernelSpecs
+end
diff --git a/spec/rubyspec/core/kernel/Integer_spec.rb b/spec/rubyspec/core/kernel/Integer_spec.rb
new file mode 100644
index 0000000000..1e95fc9151
--- /dev/null
+++ b/spec/rubyspec/core/kernel/Integer_spec.rb
@@ -0,0 +1,697 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe :kernel_integer, shared: true do
+ it "returns a Bignum for a Bignum" do
+ Integer(2e100).should == 2e100
+ end
+
+ it "returns a Fixnum for a Fixnum" do
+ Integer(100).should == 100
+ end
+
+ it "uncritically return the value of to_int even if it is not an Integer" do
+ obj = mock("object")
+ obj.should_receive(:to_int).and_return("1")
+ obj.should_not_receive(:to_i)
+ Integer(obj).should == "1"
+ end
+
+ it "raises a TypeError when passed nil" do
+ lambda { Integer(nil) }.should raise_error(TypeError)
+ end
+
+ it "returns a Fixnum or Bignum object" do
+ Integer(2).should be_an_instance_of(Fixnum)
+ Integer(9**99).should be_an_instance_of(Bignum)
+ end
+
+ it "truncates Floats" do
+ Integer(3.14).should == 3
+ Integer(90.8).should == 90
+ end
+
+ it "calls to_i on Rationals" do
+ Integer(Rational(8,3)).should == 2
+ Integer(3.quo(2)).should == 1
+ end
+
+ it "returns the value of to_int if the result is a Fixnum" do
+ obj = mock("object")
+ obj.should_receive(:to_int).and_return(1)
+ obj.should_not_receive(:to_i)
+ Integer(obj).should == 1
+ end
+
+ it "returns the value of to_int if the result is a Bignum" do
+ obj = mock("object")
+ obj.should_receive(:to_int).and_return(2e100)
+ obj.should_not_receive(:to_i)
+ Integer(obj).should == 2e100
+ end
+
+ it "calls to_i on an object whose to_int returns nil" do
+ obj = mock("object")
+ obj.should_receive(:to_int).and_return(nil)
+ obj.should_receive(:to_i).and_return(1)
+ Integer(obj).should == 1
+ end
+
+ it "raises a TypeError if to_i returns a value that is not an Integer" do
+ obj = mock("object")
+ obj.should_receive(:to_i).and_return("1")
+ lambda { Integer(obj) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if no to_int or to_i methods exist" do
+ obj = mock("object")
+ lambda { Integer(obj) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if to_int returns nil and no to_i exists" do
+ obj = mock("object")
+ obj.should_receive(:to_i).and_return(nil)
+ lambda { Integer(obj) }.should raise_error(TypeError)
+ end
+
+ it "raises a FloatDomainError when passed NaN" do
+ lambda { Integer(nan_value) }.should raise_error(FloatDomainError)
+ end
+
+ it "raises a FloatDomainError when passed Infinity" do
+ lambda { Integer(infinity_value) }.should raise_error(FloatDomainError)
+ end
+end
+
+describe "Integer() given a String", shared: true do
+ it "raises an ArgumentError if the String is a null byte" do
+ lambda { Integer("\0") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if the String starts with a null byte" do
+ lambda { Integer("\01") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if the String ends with a null byte" do
+ lambda { Integer("1\0") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if the String contains a null byte" do
+ lambda { Integer("1\01") }.should raise_error(ArgumentError)
+ end
+
+ it "ignores leading whitespace" do
+ Integer(" 1").should == 1
+ Integer(" 1").should == 1
+ Integer("\t\n1").should == 1
+ end
+
+ it "ignores trailing whitespace" do
+ Integer("1 ").should == 1
+ Integer("1 ").should == 1
+ Integer("1\t\n").should == 1
+ end
+
+ it "raises an ArgumentError if there are leading _s" do
+ lambda { Integer("_1") }.should raise_error(ArgumentError)
+ lambda { Integer("___1") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if there are trailing _s" do
+ lambda { Integer("1_") }.should raise_error(ArgumentError)
+ lambda { Integer("1___") }.should raise_error(ArgumentError)
+ end
+
+ it "ignores an embedded _" do
+ Integer("1_1").should == 11
+ end
+
+ it "raises an ArgumentError if there are multiple embedded _s" do
+ lambda { Integer("1__1") }.should raise_error(ArgumentError)
+ lambda { Integer("1___1") }.should raise_error(ArgumentError)
+ end
+
+ it "ignores a single leading +" do
+ Integer("+1").should == 1
+ end
+
+ it "raises an ArgumentError if there is a space between the + and number" do
+ lambda { Integer("+ 1") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if there are multiple leading +s" do
+ lambda { Integer("++1") }.should raise_error(ArgumentError)
+ lambda { Integer("+++1") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if there are trailing +s" do
+ lambda { Integer("1+") }.should raise_error(ArgumentError)
+ lambda { Integer("1+++") }.should raise_error(ArgumentError)
+ end
+
+ it "makes the number negative if there's a leading -" do
+ Integer("-1").should == -1
+ end
+
+ it "raises an ArgumentError if there are multiple leading -s" do
+ lambda { Integer("--1") }.should raise_error(ArgumentError)
+ lambda { Integer("---1") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if there are trailing -s" do
+ lambda { Integer("1-") }.should raise_error(ArgumentError)
+ lambda { Integer("1---") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if there is a period" do
+ lambda { Integer("0.0") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError for an empty String" do
+ lambda { Integer("") }.should raise_error(ArgumentError)
+ end
+
+ it "parses the value as 0 if the string consists of a single zero character" do
+ Integer("0").should == 0
+ end
+
+ %w(x X).each do |x|
+ it "parses the value as a hex number if there's a leading 0#{x}" do
+ Integer("0#{x}1").should == 0x1
+ Integer("0#{x}dd").should == 0xdd
+ end
+
+ it "is a positive hex number if there's a leading +0#{x}" do
+ Integer("+0#{x}1").should == 0x1
+ Integer("+0#{x}dd").should == 0xdd
+ end
+
+ it "is a negative hex number if there's a leading -0#{x}" do
+ Integer("-0#{x}1").should == -0x1
+ Integer("-0#{x}dd").should == -0xdd
+ end
+
+ it "raises an ArgumentError if the number cannot be parsed as hex" do
+ lambda { Integer("0#{x}g") }.should raise_error(ArgumentError)
+ end
+ end
+
+ %w(b B).each do |b|
+ it "parses the value as a binary number if there's a leading 0#{b}" do
+ Integer("0#{b}1").should == 0b1
+ Integer("0#{b}10").should == 0b10
+ end
+
+ it "is a positive binary number if there's a leading +0#{b}" do
+ Integer("+0#{b}1").should == 0b1
+ Integer("+0#{b}10").should == 0b10
+ end
+
+ it "is a negative binary number if there's a leading -0#{b}" do
+ Integer("-0#{b}1").should == -0b1
+ Integer("-0#{b}10").should == -0b10
+ end
+
+ it "raises an ArgumentError if the number cannot be parsed as binary" do
+ lambda { Integer("0#{b}2") }.should raise_error(ArgumentError)
+ end
+ end
+
+ ["o", "O", ""].each do |o|
+ it "parses the value as an octal number if there's a leading 0#{o}" do
+ Integer("0#{o}1").should == 0O1
+ Integer("0#{o}10").should == 0O10
+ end
+
+ it "is a positive octal number if there's a leading +0#{o}" do
+ Integer("+0#{o}1").should == 0O1
+ Integer("+0#{o}10").should == 0O10
+ end
+
+ it "is a negative octal number if there's a leading -0#{o}" do
+ Integer("-0#{o}1").should == -0O1
+ Integer("-0#{o}10").should == -0O10
+ end
+
+ it "raises an ArgumentError if the number cannot be parsed as octal" do
+ lambda { Integer("0#{o}9") }.should raise_error(ArgumentError)
+ end
+ end
+
+ %w(D d).each do |d|
+ it "parses the value as a decimal number if there's a leading 0#{d}" do
+ Integer("0#{d}1").should == 1
+ Integer("0#{d}10").should == 10
+ end
+
+ it "is a positive decimal number if there's a leading +0#{d}" do
+ Integer("+0#{d}1").should == 1
+ Integer("+0#{d}10").should == 10
+ end
+
+ it "is a negative decimal number if there's a leading -0#{d}" do
+ Integer("-0#{d}1").should == -1
+ Integer("-0#{d}10").should == -10
+ end
+
+ it "raises an ArgumentError if the number cannot be parsed as decimal" do
+ lambda { Integer("0#{d}a") }.should raise_error(ArgumentError)
+ end
+ end
+end
+
+describe "Integer() given a String and base", shared: true do
+ it "raises an ArgumentError if the String is a null byte" do
+ lambda { Integer("\0", 2) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if the String starts with a null byte" do
+ lambda { Integer("\01", 3) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if the String ends with a null byte" do
+ lambda { Integer("1\0", 4) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if the String contains a null byte" do
+ lambda { Integer("1\01", 5) }.should raise_error(ArgumentError)
+ end
+
+ it "ignores leading whitespace" do
+ Integer(" 16", 16).should == 22
+ Integer(" 16", 16).should == 22
+ Integer("\t\n16", 16).should == 22
+ end
+
+ it "ignores trailing whitespace" do
+ Integer("16 ", 16).should == 22
+ Integer("16 ", 16).should == 22
+ Integer("16\t\n", 16).should == 22
+ end
+
+ it "raises an ArgumentError if there are leading _s" do
+ lambda { Integer("_1", 7) }.should raise_error(ArgumentError)
+ lambda { Integer("___1", 7) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if there are trailing _s" do
+ lambda { Integer("1_", 12) }.should raise_error(ArgumentError)
+ lambda { Integer("1___", 12) }.should raise_error(ArgumentError)
+ end
+
+ it "ignores an embedded _" do
+ Integer("1_1", 4).should == 5
+ end
+
+ it "raises an ArgumentError if there are multiple embedded _s" do
+ lambda { Integer("1__1", 4) }.should raise_error(ArgumentError)
+ lambda { Integer("1___1", 4) }.should raise_error(ArgumentError)
+ end
+
+ it "ignores a single leading +" do
+ Integer("+10", 3).should == 3
+ end
+
+ it "raises an ArgumentError if there is a space between the + and number" do
+ lambda { Integer("+ 1", 3) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if there are multiple leading +s" do
+ lambda { Integer("++1", 3) }.should raise_error(ArgumentError)
+ lambda { Integer("+++1", 3) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if there are trailing +s" do
+ lambda { Integer("1+", 3) }.should raise_error(ArgumentError)
+ lambda { Integer("1+++", 12) }.should raise_error(ArgumentError)
+ end
+
+ it "makes the number negative if there's a leading -" do
+ Integer("-19", 20).should == -29
+ end
+
+ it "raises an ArgumentError if there are multiple leading -s" do
+ lambda { Integer("--1", 9) }.should raise_error(ArgumentError)
+ lambda { Integer("---1", 9) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if there are trailing -s" do
+ lambda { Integer("1-", 12) }.should raise_error(ArgumentError)
+ lambda { Integer("1---", 12) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if there is a period" do
+ lambda { Integer("0.0", 3) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError for an empty String" do
+ lambda { Integer("", 12) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError for a base of 1" do
+ lambda { Integer("1", 1) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError for a base of 37" do
+ lambda { Integer("1", 37) }.should raise_error(ArgumentError)
+ end
+
+ it "accepts wholly lowercase alphabetic strings for bases > 10" do
+ Integer('ab',12).should == 131
+ Integer('af',20).should == 215
+ Integer('ghj',30).should == 14929
+ end
+
+ it "accepts wholly uppercase alphabetic strings for bases > 10" do
+ Integer('AB',12).should == 131
+ Integer('AF',20).should == 215
+ Integer('GHJ',30).should == 14929
+ end
+
+ it "accepts mixed-case alphabetic strings for bases > 10" do
+ Integer('Ab',12).should == 131
+ Integer('aF',20).should == 215
+ Integer('GhJ',30).should == 14929
+ end
+
+ it "accepts alphanumeric strings for bases > 10" do
+ Integer('a3e',19).should == 3681
+ Integer('12q',31).should == 1049
+ Integer('c00o',29).should == 292692
+ end
+
+ it "raises an ArgumentError for letters invalid in the given base" do
+ lambda { Integer('z',19) }.should raise_error(ArgumentError)
+ lambda { Integer('c00o',2) }.should raise_error(ArgumentError)
+ end
+
+ %w(x X).each do |x|
+ it "parses the value as a hex number if there's a leading 0#{x} and a base of 16" do
+ Integer("0#{x}10", 16).should == 16
+ Integer("0#{x}dd", 16).should == 221
+ end
+
+ it "is a positive hex number if there's a leading +0#{x} and base of 16" do
+ Integer("+0#{x}1", 16).should == 0x1
+ Integer("+0#{x}dd", 16).should == 0xdd
+ end
+
+ it "is a negative hex number if there's a leading -0#{x} and a base of 16" do
+ Integer("-0#{x}1", 16).should == -0x1
+ Integer("-0#{x}dd", 16).should == -0xdd
+ end
+
+ 2.upto(15) do |base|
+ it "raises an ArgumentError if the number begins with 0#{x} and the base is #{base}" do
+ lambda { Integer("0#{x}1", base) }.should raise_error(ArgumentError)
+ end
+ end
+
+ it "raises an ArgumentError if the number cannot be parsed as hex and the base is 16" do
+ lambda { Integer("0#{x}g", 16) }.should raise_error(ArgumentError)
+ end
+ end
+
+ %w(b B).each do |b|
+ it "parses the value as a binary number if there's a leading 0#{b} and the base is 2" do
+ Integer("0#{b}1", 2).should == 0b1
+ Integer("0#{b}10", 2).should == 0b10
+ end
+
+ it "is a positive binary number if there's a leading +0#{b} and a base of 2" do
+ Integer("+0#{b}1", 2).should == 0b1
+ Integer("+0#{b}10", 2).should == 0b10
+ end
+
+ it "is a negative binary number if there's a leading -0#{b} and a base of 2" do
+ Integer("-0#{b}1", 2).should == -0b1
+ Integer("-0#{b}10", 2).should == -0b10
+ end
+
+ it "raises an ArgumentError if the number cannot be parsed as binary and the base is 2" do
+ lambda { Integer("0#{b}2", 2) }.should raise_error(ArgumentError)
+ end
+ end
+
+ ["o", "O"].each do |o|
+ it "parses the value as an octal number if there's a leading 0#{o} and a base of 8" do
+ Integer("0#{o}1", 8).should == 0O1
+ Integer("0#{o}10", 8).should == 0O10
+ end
+
+ it "is a positive octal number if there's a leading +0#{o} and a base of 8" do
+ Integer("+0#{o}1", 8).should == 0O1
+ Integer("+0#{o}10", 8).should == 0O10
+ end
+
+ it "is a negative octal number if there's a leading -0#{o} and a base of 8" do
+ Integer("-0#{o}1", 8).should == -0O1
+ Integer("-0#{o}10", 8).should == -0O10
+ end
+
+ it "raises an ArgumentError if the number cannot be parsed as octal and the base is 8" do
+ lambda { Integer("0#{o}9", 8) }.should raise_error(ArgumentError)
+ end
+
+ 2.upto(7) do |base|
+ it "raises an ArgumentError if the number begins with 0#{o} and the base is #{base}" do
+ lambda { Integer("0#{o}1", base) }.should raise_error(ArgumentError)
+ end
+ end
+ end
+
+ %w(D d).each do |d|
+ it "parses the value as a decimal number if there's a leading 0#{d} and a base of 10" do
+ Integer("0#{d}1", 10).should == 1
+ Integer("0#{d}10",10).should == 10
+ end
+
+ it "is a positive decimal number if there's a leading +0#{d} and a base of 10" do
+ Integer("+0#{d}1", 10).should == 1
+ Integer("+0#{d}10", 10).should == 10
+ end
+
+ it "is a negative decimal number if there's a leading -0#{d} and a base of 10" do
+ Integer("-0#{d}1", 10).should == -1
+ Integer("-0#{d}10", 10).should == -10
+ end
+
+ it "raises an ArgumentError if the number cannot be parsed as decimal and the base is 10" do
+ lambda { Integer("0#{d}a", 10) }.should raise_error(ArgumentError)
+ end
+
+ 2.upto(9) do |base|
+ it "raises an ArgumentError if the number begins with 0#{d} and the base is #{base}" do
+ lambda { Integer("0#{d}1", base) }.should raise_error(ArgumentError)
+ end
+ end
+
+ it "raises an ArgumentError if a base is given for a non-String value" do
+ lambda { Integer(98, 15) }.should raise_error(ArgumentError)
+ end
+ end
+end
+
+describe :kernel_Integer, shared: true do
+ it "raises an ArgumentError when the String contains digits out of range of radix 2" do
+ str = "23456789abcdefghijklmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 2) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 3" do
+ str = "3456789abcdefghijklmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 3) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 4" do
+ str = "456789abcdefghijklmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 4) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 5" do
+ str = "56789abcdefghijklmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 5) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 6" do
+ str = "6789abcdefghijklmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 6) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 7" do
+ str = "789abcdefghijklmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 7) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 8" do
+ str = "89abcdefghijklmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 8) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 9" do
+ str = "9abcdefghijklmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 9) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 10" do
+ str = "abcdefghijklmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 10) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 11" do
+ str = "bcdefghijklmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 11) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 12" do
+ str = "cdefghijklmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 12) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 13" do
+ str = "defghijklmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 13) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 14" do
+ str = "efghijklmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 14) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 15" do
+ str = "fghijklmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 15) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 16" do
+ str = "ghijklmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 16) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 17" do
+ str = "hijklmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 17) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 18" do
+ str = "ijklmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 18) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 19" do
+ str = "jklmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 19) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 20" do
+ str = "klmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 20) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 21" do
+ str = "lmnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 21) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 22" do
+ str = "mnopqrstuvwxyz"
+ lambda { @object.send(@method, str, 22) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 23" do
+ str = "nopqrstuvwxyz"
+ lambda { @object.send(@method, str, 23) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 24" do
+ str = "opqrstuvwxyz"
+ lambda { @object.send(@method, str, 24) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 25" do
+ str = "pqrstuvwxyz"
+ lambda { @object.send(@method, str, 25) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 26" do
+ str = "qrstuvwxyz"
+ lambda { @object.send(@method, str, 26) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 27" do
+ str = "rstuvwxyz"
+ lambda { @object.send(@method, str, 27) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 28" do
+ str = "stuvwxyz"
+ lambda { @object.send(@method, str, 28) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 29" do
+ str = "tuvwxyz"
+ lambda { @object.send(@method, str, 29) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 30" do
+ str = "uvwxyz"
+ lambda { @object.send(@method, str, 30) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 31" do
+ str = "vwxyz"
+ lambda { @object.send(@method, str, 31) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 32" do
+ str = "wxyz"
+ lambda { @object.send(@method, str, 32) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 33" do
+ str = "xyz"
+ lambda { @object.send(@method, str, 33) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 34" do
+ str = "yz"
+ lambda { @object.send(@method, str, 34) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 35" do
+ str = "z"
+ lambda { @object.send(@method, str, 35) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when the String contains digits out of range of radix 36" do
+ lambda { @object.send(@method, "{", 36) }.should raise_error(ArgumentError)
+ end
+end
+
+describe "Kernel.Integer" do
+ it_behaves_like :kernel_Integer, :Integer_method, KernelSpecs
+
+ # TODO: fix these specs
+ it_behaves_like :kernel_integer, :Integer, Kernel
+ it_behaves_like "Integer() given a String", :Integer
+
+ it_behaves_like "Integer() given a String and base", :Integer
+
+ it "is a public method" do
+ Kernel.Integer(10).should == 10
+ end
+end
+
+describe "Kernel#Integer" do
+ it_behaves_like :kernel_Integer, :Integer_function, KernelSpecs
+
+ # TODO: fix these specs
+ it_behaves_like :kernel_integer, :Integer, Object.new
+ it_behaves_like "Integer() given a String", :Integer
+
+ it_behaves_like "Integer() given a String and base", :Integer
+
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:Integer)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/Rational_spec.rb b/spec/rubyspec/core/kernel/Rational_spec.rb
new file mode 100644
index 0000000000..38f1da6333
--- /dev/null
+++ b/spec/rubyspec/core/kernel/Rational_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../../../shared/rational/Rational', __FILE__)
+
+describe "Kernel.Rational" do
+ it_behaves_like :kernel_Rational, :Rational
+end
diff --git a/spec/rubyspec/core/kernel/String_spec.rb b/spec/rubyspec/core/kernel/String_spec.rb
new file mode 100644
index 0000000000..b24bc798e5
--- /dev/null
+++ b/spec/rubyspec/core/kernel/String_spec.rb
@@ -0,0 +1,106 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe :kernel_String, shared: true do
+ it "converts nil to a String" do
+ @object.send(@method, nil).should == ""
+ end
+
+ it "converts a Float to a String" do
+ @object.send(@method, 1.12).should == "1.12"
+ end
+
+ it "converts a boolean to a String" do
+ @object.send(@method, false).should == "false"
+ @object.send(@method, true).should == "true"
+ end
+
+ it "converts a constant to a String" do
+ @object.send(@method, Object).should == "Object"
+ end
+
+ it "calls #to_s to convert an arbitrary object to a String" do
+ obj = mock('test')
+ obj.should_receive(:to_s).and_return("test")
+
+ @object.send(@method, obj).should == "test"
+ end
+
+ it "raises a TypeError if #to_s does not exist" do
+ obj = mock('to_s')
+ class << obj
+ undef_method :to_s
+ end
+
+ lambda { @object.send(@method, obj) }.should raise_error(TypeError)
+ end
+
+ # #5158
+ it "raises a TypeError if respond_to? returns false for #to_s" do
+ obj = mock("to_s")
+ class << obj
+ def respond_to?(meth, include_private=false)
+ meth == :to_s ? false : super
+ end
+ end
+
+ lambda { @object.send(@method, obj) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if #to_s is not defined, even though #respond_to?(:to_s) returns true" do
+ # cannot use a mock because of how RSpec affects #method_missing
+ obj = Object.new
+ class << obj
+ undef_method :to_s
+ def respond_to?(meth, include_private=false)
+ meth == :to_s ? true : super
+ end
+ end
+
+ lambda { @object.send(@method, obj) }.should raise_error(TypeError)
+ end
+
+ it "calls #to_s if #respond_to?(:to_s) returns true" do
+ obj = mock('to_s')
+ class << obj
+ undef_method :to_s
+ def method_missing(meth, *args)
+ meth == :to_s ? "test" : super
+ end
+ end
+
+ @object.send(@method, obj).should == "test"
+ end
+
+ it "raises a TypeError if #to_s does not return a String" do
+ (obj = mock('123')).should_receive(:to_s).and_return(123)
+ lambda { @object.send(@method, obj) }.should raise_error(TypeError)
+ end
+
+ it "returns the same object if it is already a String" do
+ string = "Hello"
+ string.should_not_receive(:to_s)
+ string2 = @object.send(@method, string)
+ string.should equal(string2)
+ end
+
+ it "returns the same object if it is an instance of a String subclass" do
+ subklass = Class.new(String)
+ string = subklass.new("Hello")
+ string.should_not_receive(:to_s)
+ string2 = @object.send(@method, string)
+ string.should equal(string2)
+ end
+end
+
+describe "Kernel.String" do
+ it_behaves_like :kernel_String, :String, Kernel
+end
+
+describe "Kernel#String" do
+ it_behaves_like :kernel_String, :String, Object.new
+
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:String)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/__callee___spec.rb b/spec/rubyspec/core/kernel/__callee___spec.rb
new file mode 100644
index 0000000000..91cc4cdafa
--- /dev/null
+++ b/spec/rubyspec/core/kernel/__callee___spec.rb
@@ -0,0 +1,48 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/__callee__', __FILE__)
+
+describe "Kernel.__callee__" do
+ it "returns the current method, even when aliased" do
+ KernelSpecs::CalleeTest.new.f.should == :f
+ end
+
+ it "returns the aliased name when aliased method" do
+ KernelSpecs::CalleeTest.new.g.should == :g
+ end
+
+ it "returns the caller from blocks too" do
+ KernelSpecs::CalleeTest.new.in_block.should == [:in_block, :in_block]
+ end
+
+ it "returns the caller from define_method too" do
+ KernelSpecs::CalleeTest.new.dm.should == :dm
+ end
+
+ it "returns the caller from block inside define_method too" do
+ KernelSpecs::CalleeTest.new.dm_block.should == [:dm_block, :dm_block]
+ end
+
+ it "returns method name even from send" do
+ KernelSpecs::CalleeTest.new.from_send.should == :from_send
+ end
+
+ it "returns method name even from eval" do
+ KernelSpecs::CalleeTest.new.from_eval.should == :from_eval
+ end
+
+ it "returns nil from inside a class body" do
+ KernelSpecs::CalleeTest.new.from_class_body.should == nil
+ end
+
+ it "returns nil when not called from a method" do
+ __callee__.should == nil
+ end
+
+ it "returns the caller from a define_method called from the same class" do
+ c = Class.new do
+ define_method(:f) { 1.times{ break __callee__ } }
+ def g; f end
+ end
+ c.new.g.should == :f
+ end
+end
diff --git a/spec/rubyspec/core/kernel/__dir___spec.rb b/spec/rubyspec/core/kernel/__dir___spec.rb
new file mode 100644
index 0000000000..395d30f494
--- /dev/null
+++ b/spec/rubyspec/core/kernel/__dir___spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Kernel#__dir__" do
+ it "returns the real name of the directory containing the currently-executing file" do
+ __dir__.should == File.realpath(File.dirname(__FILE__))
+ end
+
+ context "when used in eval with top level binding" do
+ it "returns the real name of the directory containing the currently-executing file" do
+ eval("__dir__", binding).should == File.realpath(File.dirname(__FILE__))
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/__method___spec.rb b/spec/rubyspec/core/kernel/__method___spec.rb
new file mode 100644
index 0000000000..936a6b2f00
--- /dev/null
+++ b/spec/rubyspec/core/kernel/__method___spec.rb
@@ -0,0 +1,40 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/__method__', __FILE__)
+
+describe "Kernel.__method__" do
+ it "returns the current method, even when aliased" do
+ KernelSpecs::MethodTest.new.f.should == :f
+ end
+
+ it "returns the original name when aliased method" do
+ KernelSpecs::MethodTest.new.g.should == :f
+ end
+
+ it "returns the caller from blocks too" do
+ KernelSpecs::MethodTest.new.in_block.should == [:in_block, :in_block]
+ end
+
+ it "returns the caller from define_method too" do
+ KernelSpecs::MethodTest.new.dm.should == :dm
+ end
+
+ it "returns the caller from block inside define_method too" do
+ KernelSpecs::MethodTest.new.dm_block.should == [:dm_block, :dm_block]
+ end
+
+ it "returns method name even from send" do
+ KernelSpecs::MethodTest.new.from_send.should == :from_send
+ end
+
+ it "returns method name even from eval" do
+ KernelSpecs::MethodTest.new.from_eval.should == :from_eval
+ end
+
+ it "returns nil from inside a class body" do
+ KernelSpecs::MethodTest.new.from_class_body.should == nil
+ end
+
+ it "returns nil when not called from a method" do
+ __method__.should == nil
+ end
+end
diff --git a/spec/rubyspec/core/kernel/abort_spec.rb b/spec/rubyspec/core/kernel/abort_spec.rb
new file mode 100644
index 0000000000..eb9c1c30c7
--- /dev/null
+++ b/spec/rubyspec/core/kernel/abort_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../../../shared/process/abort', __FILE__)
+
+describe "Kernel#abort" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:abort)
+ end
+
+ it_behaves_like :process_abort, :abort, KernelSpecs::Method.new
+end
+
+describe "Kernel.abort" do
+ it_behaves_like :process_abort, :abort, Kernel
+end
diff --git a/spec/rubyspec/core/kernel/at_exit_spec.rb b/spec/rubyspec/core/kernel/at_exit_spec.rb
new file mode 100644
index 0000000000..9fcb99148c
--- /dev/null
+++ b/spec/rubyspec/core/kernel/at_exit_spec.rb
@@ -0,0 +1,44 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel.at_exit" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:at_exit)
+ end
+
+ it "runs after all other code" do
+ ruby_exe("at_exit {print 5}; print 6").should == "65"
+ end
+
+ it "runs in reverse order of registration" do
+ code = "at_exit {print 4};at_exit {print 5}; print 6; at_exit {print 7}"
+ ruby_exe(code).should == "6754"
+ end
+
+ it "allows calling exit inside at_exit handler" do
+ code = "at_exit {print 3}; at_exit {print 4; exit; print 5}; at_exit {print 6}"
+ ruby_exe(code).should == "643"
+ end
+
+ it "gives access to the last raised exception" do
+ code = <<-EOC
+ at_exit do
+ puts "The exception matches: \#{$! == $exception}"
+ end
+
+ begin
+ raise "foo"
+ rescue => $exception
+ raise
+ end
+ EOC
+
+ result = ruby_exe(code, args: "2>&1", escape: true)
+ result.should =~ /The exception matches: true/
+ end
+
+end
+
+describe "Kernel#at_exit" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/autoload_spec.rb b/spec/rubyspec/core/kernel/autoload_spec.rb
new file mode 100644
index 0000000000..082903e92d
--- /dev/null
+++ b/spec/rubyspec/core/kernel/autoload_spec.rb
@@ -0,0 +1,122 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+# These specs only illustrate the basic autoload cases
+# and where toplevel autoload behaves differently from
+# Module#autoload. See those specs for more examples.
+
+autoload :KSAutoloadA, "autoload_a.rb"
+autoload :KSAutoloadB, fixture(__FILE__, "autoload_b.rb")
+autoload :KSAutoloadC, fixture(__FILE__, "autoload_c.rb")
+
+def check_autoload(const)
+ autoload? const
+end
+
+describe "Kernel#autoload" do
+ before :each do
+ @loaded_features = $".dup
+ end
+
+ after :each do
+ $".replace @loaded_features
+ end
+
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:autoload)
+ end
+
+ it "registers a file to load the first time the named constant is accessed" do
+ Object.autoload?(:KSAutoloadA).should == "autoload_a.rb"
+ end
+
+ it "registers a file to load the first time the named constant is accessed" do
+ check_autoload(:KSAutoloadA).should == "autoload_a.rb"
+ end
+
+ it "sets the autoload constant in Object's constant table" do
+ Object.should have_constant(:KSAutoloadA)
+ end
+
+ it "loads the file when the constant is accessed" do
+ KSAutoloadB.loaded.should == :ksautoload_b
+ end
+
+ it "does not call Kernel.require or Kernel.load to load the file" do
+ Kernel.should_not_receive(:require)
+ Kernel.should_not_receive(:load)
+ KSAutoloadC.loaded.should == :ksautoload_c
+ end
+
+ it "can autoload in instance_eval" do
+ instance_eval do
+ # this instance_eval is not needed because specs are run in instance_eval
+ autoload :KSAutoloadD, fixture(__FILE__, "autoload_d.rb")
+ KSAutoloadD.loaded.should == :ksautoload_d
+ end
+ end
+
+ describe "when Object is frozen" do
+ it "raises a RuntimeError before defining the constant" do
+ ruby_exe(fixture(__FILE__, "autoload_frozen.rb")).should == "RuntimeError - nil"
+ end
+ end
+end
+
+describe "Kernel#autoload?" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:autoload?)
+ end
+
+ it "returns the name of the file that will be autoloaded" do
+ check_autoload(:KSAutoloadA).should == "autoload_a.rb"
+ end
+
+ it "returns nil if no file has been registered for a constant" do
+ check_autoload(:Manualload).should be_nil
+ end
+end
+
+Kernel.autoload :KSAutoloadBB, "no_autoload.rb"
+
+describe "Kernel.autoload" do
+ before :all do
+ @non_existent = fixture __FILE__, "no_autoload.rb"
+ end
+
+ before :each do
+ @loaded_features = $".dup
+
+ ScratchPad.clear
+ end
+
+ after :each do
+ $".replace @loaded_features
+ end
+
+ it "registers a file to load the first time the toplevel constant is accessed" do
+ Kernel.autoload :KSAutoloadAA, @non_existent
+ Kernel.autoload?(:KSAutoloadAA).should == @non_existent
+ end
+
+ it "sets the autoload constant in Object's constant table" do
+ Object.should have_constant(:KSAutoloadBB)
+ end
+
+ it "calls #to_path on non-String filenames" do
+ p = mock('path')
+ p.should_receive(:to_path).and_return @non_existent
+ Kernel.autoload :KSAutoloadAA, p
+ end
+end
+
+describe "Kernel.autoload?" do
+ it "returns the name of the file that will be autoloaded" do
+ Kernel.autoload :KSAutoload, "autoload.rb"
+ Kernel.autoload?(:KSAutoload).should == "autoload.rb"
+ end
+
+ it "returns nil if no file has been registered for a constant" do
+ Kernel.autoload?(:Manualload).should be_nil
+ end
+end
diff --git a/spec/rubyspec/core/kernel/backtick_spec.rb b/spec/rubyspec/core/kernel/backtick_spec.rb
new file mode 100644
index 0000000000..eb25750bc2
--- /dev/null
+++ b/spec/rubyspec/core/kernel/backtick_spec.rb
@@ -0,0 +1,80 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#`" do
+ before :each do
+ @original_external = Encoding.default_external
+ end
+
+ after :each do
+ Encoding.default_external = @original_external
+ end
+
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:`)
+ end
+
+ it "returns the standard output of the executed sub-process" do
+ ip = 'world'
+ `echo disc #{ip}`.should == "disc world\n"
+ end
+
+ it "lets the standard error stream pass through to the inherited stderr" do
+ cmd = ruby_cmd('STDERR.print "error stream"')
+ lambda {
+ `#{cmd}`.should == ""
+ }.should output_to_fd("error stream", STDERR)
+ end
+
+ it "produces a String in the default external encoding" do
+ Encoding.default_external = Encoding::SHIFT_JIS
+ `echo disc`.encoding.should equal(Encoding::SHIFT_JIS)
+ end
+
+ it "raises an Errno::ENOENT if the command is not executable" do
+ lambda { `nonexistent_command` }.should raise_error(Errno::ENOENT)
+ end
+
+ platform_is_not :windows do
+ it "sets $? to the exit status of the executed sub-process" do
+ ip = 'world'
+ `echo disc #{ip}`
+ $?.should be_kind_of(Process::Status)
+ $?.stopped?.should == false
+ $?.exited?.should == true
+ $?.exitstatus.should == 0
+ $?.success?.should == true
+ `echo disc #{ip}; exit 99`
+ $?.should be_kind_of(Process::Status)
+ $?.stopped?.should == false
+ $?.exited?.should == true
+ $?.exitstatus.should == 99
+ $?.success?.should == false
+ end
+ end
+
+ platform_is :windows do
+ it "sets $? to the exit status of the executed sub-process" do
+ ip = 'world'
+ `echo disc #{ip}`
+ $?.should be_kind_of(Process::Status)
+ $?.stopped?.should == false
+ $?.exited?.should == true
+ $?.exitstatus.should == 0
+ $?.success?.should == true
+ `echo disc #{ip}& exit 99`
+ $?.should be_kind_of(Process::Status)
+ $?.stopped?.should == false
+ $?.exited?.should == true
+ $?.exitstatus.should == 99
+ $?.success?.should == false
+ end
+ end
+end
+
+describe "Kernel.`" do
+ it "tries to convert the given argument to String using #to_str" do
+ (obj = mock('echo test')).should_receive(:to_str).and_return("echo test")
+ Kernel.`(obj).should == "test\n" #` fix vim syntax highlighting
+ end
+end
diff --git a/spec/rubyspec/core/kernel/binding_spec.rb b/spec/rubyspec/core/kernel/binding_spec.rb
new file mode 100644
index 0000000000..0b33c86d3c
--- /dev/null
+++ b/spec/rubyspec/core/kernel/binding_spec.rb
@@ -0,0 +1,51 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel.binding" do
+ it "returns a binding for the caller" do
+ Kernel.binding.eval("self").should == self
+ end
+end
+
+describe "Kernel#binding" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:binding)
+ end
+
+ before :each do
+ @b1 = KernelSpecs::Binding.new(99).get_binding
+ ScratchPad.clear
+ end
+
+ it "returns a Binding object" do
+ @b1.kind_of?(Binding).should == true
+ end
+
+ it "encapsulates the execution context properly" do
+ eval("@secret", @b1).should == 100
+ eval("a", @b1).should == true
+ eval("b", @b1).should == true
+ eval("@@super_secret", @b1).should == "password"
+
+ eval("square(2)", @b1).should == 4
+ eval("self.square(2)", @b1).should == 4
+
+ eval("a = false", @b1)
+ eval("a", @b1).should == false
+ end
+
+ it "raises a NameError on undefined variable" do
+ lambda { eval("a_fake_variable", @b1) }.should raise_error(NameError)
+ end
+
+ it "uses the closure's self as self in the binding" do
+ m = mock(:whatever)
+ eval('self', m.send(:binding)).should == self
+ end
+
+ it "uses the class as self in a Class.new block" do
+ m = mock(:whatever)
+ cls = Class.new { ScratchPad.record eval('self', m.send(:binding)) }
+ ScratchPad.recorded.should == cls
+ end
+end
diff --git a/spec/rubyspec/core/kernel/block_given_spec.rb b/spec/rubyspec/core/kernel/block_given_spec.rb
new file mode 100644
index 0000000000..9454c938ae
--- /dev/null
+++ b/spec/rubyspec/core/kernel/block_given_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe :kernel_block_given, shared: true do
+ it "returns true if and only if a block is supplied" do
+ @object.accept_block {}.should == true
+ @object.accept_block_as_argument {}.should == true
+
+ @object.accept_block.should == false
+ @object.accept_block_as_argument.should == false
+ end
+
+ # Clarify: Based on http://www.ruby-forum.com/topic/137822 it appears
+ # that Matz wanted this to be true in 1.9.
+ it "returns false when a method defined by define_method is called with a block" do
+ @object.defined_block {}.should == false
+ end
+end
+
+describe "Kernel#block_given?" do
+ it_behaves_like :kernel_block_given, :block_given?, KernelSpecs::BlockGiven
+
+ it "returns false outside of a method" do
+ block_given?.should == false
+ end
+
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:block_given?)
+ end
+end
+
+describe "Kernel.block_given?" do
+ it_behaves_like :kernel_block_given, :block_given?, KernelSpecs::KernelBlockGiven
+end
+
+describe "self.send(:block_given?)" do
+ it_behaves_like :kernel_block_given, :block_given?, KernelSpecs::SelfBlockGiven
+end
diff --git a/spec/rubyspec/core/kernel/caller_locations_spec.rb b/spec/rubyspec/core/kernel/caller_locations_spec.rb
new file mode 100644
index 0000000000..69993c3ec0
--- /dev/null
+++ b/spec/rubyspec/core/kernel/caller_locations_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/caller_locations', __FILE__)
+
+describe 'Kernel#caller_locations' do
+ it 'is a private method' do
+ Kernel.should have_private_instance_method(:caller_locations)
+ end
+
+ it 'returns an Array of caller locations' do
+ KernelSpecs::CallerLocationsTest.locations.empty?.should == false
+ end
+
+ it 'returns an Array of caller locations using a custom offset' do
+ locations = KernelSpecs::CallerLocationsTest.locations(2)
+
+ locations[0].absolute_path.end_with?('mspec.rb').should == true
+ end
+
+ it 'returns an Array of caller locations using a custom limit' do
+ locations = KernelSpecs::CallerLocationsTest.locations(1, 1)
+
+ locations.length.should == 1
+ end
+
+ it 'returns the locations as Thread::Backtrace::Location instances' do
+ locations = KernelSpecs::CallerLocationsTest.locations
+
+ locations.each do |location|
+ location.kind_of?(Thread::Backtrace::Location).should == true
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/caller_spec.rb b/spec/rubyspec/core/kernel/caller_spec.rb
new file mode 100644
index 0000000000..94fbe3ab7e
--- /dev/null
+++ b/spec/rubyspec/core/kernel/caller_spec.rb
@@ -0,0 +1,31 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/caller', __FILE__)
+
+describe 'Kernel#caller' do
+ it 'is a private method' do
+ Kernel.should have_private_instance_method(:caller)
+ end
+
+ it 'returns an Array of caller locations' do
+ KernelSpecs::CallerTest.locations.empty?.should == false
+ end
+
+ it 'returns an Array of caller locations using a custom offset' do
+ locations = KernelSpecs::CallerTest.locations(2)
+
+ locations[0].should =~ %r{runner/mspec.rb}
+ end
+
+ it 'returns an Array of caller locations using a custom limit' do
+ locations = KernelSpecs::CallerTest.locations(1, 1)
+
+ locations.length.should == 1
+ end
+
+ it 'returns the locations as String instances' do
+ locations = KernelSpecs::CallerTest.locations
+ line = __LINE__ - 1
+
+ locations[0].should include("#{__FILE__}:#{line}:in")
+ end
+end
diff --git a/spec/rubyspec/core/kernel/case_compare_spec.rb b/spec/rubyspec/core/kernel/case_compare_spec.rb
new file mode 100644
index 0000000000..5332aa7647
--- /dev/null
+++ b/spec/rubyspec/core/kernel/case_compare_spec.rb
@@ -0,0 +1,135 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+
+module Specs
+ module Kernel
+
+ class HasNone
+ end
+
+ class HasOpEqual
+ def ==(other)
+ other.kind_of? HasOpEqual
+ end
+ end
+
+ class HasEqual
+ def equal?(other)
+ false
+ end
+ end
+
+ class HasOppoOpEqual
+ def ==(other)
+ false
+ end
+
+ def equal?(other)
+ false
+ end
+ end
+ end
+end
+
+
+describe "Kernel#=== for a class with default #== and #equal?" do
+ before :each do
+ @o1 = Specs::Kernel::HasNone.new
+ @o2 = @o1.dup
+ end
+
+ it "returns true if other object has same object id" do
+ @o1.object_id.should == @o1.object_id
+ (@o1 === @o1).should == true
+ end
+
+ it "returns false if other object does not have same object id" do
+ @o1.object_id.should_not == @o2.object_id
+ (@o1 === @o2).should == false
+ end
+end
+
+describe "Kernel#=== for a class with #== overridden to consider other object's class" do
+ before :each do
+ @o = Object.new
+ @o1 = Specs::Kernel::HasOpEqual.new
+ @o2 = @o1.dup
+ end
+
+ it "returns true if #== returns true even if #equal? is false" do
+ @o1.should_not equal(@o2)
+ (@o1 == @o2).should == true
+ (@o1 === @o2).should == true
+ end
+
+ it "returns true if #equal? returns true" do
+ @o1.should equal(@o1)
+ (@o1 === @o1).should == true
+ end
+
+ it "returns false if neither #== nor #equal? returns true" do
+ @o1.should_not equal(@o)
+ (@o1 == @o).should == false
+ (@o1 === @o).should == false
+ end
+end
+
+describe "Kernel#=== for a class with #equal? overridden to always be false" do
+ before :each do
+ @o = Object.new
+ @o1 = Specs::Kernel::HasEqual.new
+ @o2 = @o1.dup
+ end
+
+ it "returns true if #== returns true even if #equal? is false" do
+ @o1.should_not equal(@o1)
+ (@o1 == @o1).should == true
+ (@o1 === @o1).should == true
+ end
+
+ it "returns false if neither #== nor #equal? returns true" do
+ @o1.should_not equal(@o)
+ (@o1 == @o).should == false
+ (@o1 === @o).should == false
+ end
+end
+
+describe "Kernel#=== for a class with #== and #equal? overridden to always be false" do
+ before :each do
+ @o = Object.new
+ @o1 = Specs::Kernel::HasOppoOpEqual.new
+ @o2 = @o1.dup
+ end
+
+ it "returns true if the object id is the same even if both #== and #equal? return false" do
+ @o1.object_id.should == @o1.object_id
+
+ @o1.should_not equal(@o1)
+ (@o1 == @o1).should == false
+
+ (@o1 === @o1).should == true
+ end
+
+ it "returns false if the object id is not the same and both #== and #equal? return false" do
+ @o1.object_id.should_not == @o2.object_id
+
+ @o1.should_not equal(@o2)
+ (@o1 == @o2).should == false
+
+ (@o1 === @o2).should == false
+ end
+end
+
+describe "Kernel#=== does not call #object_id nor #equal?" do
+ before :each do
+ @o1 = Object.new
+ @o1.should_not_receive(:object_id)
+ @o1.should_not_receive(:equal?)
+ end
+
+ it "but still returns true for #== or #=== on the same object" do
+ (@o1 == @o1).should == true
+ (@o1 === @o1).should == true
+ end
+end
diff --git a/spec/rubyspec/core/kernel/catch_spec.rb b/spec/rubyspec/core/kernel/catch_spec.rb
new file mode 100644
index 0000000000..35a4860f38
--- /dev/null
+++ b/spec/rubyspec/core/kernel/catch_spec.rb
@@ -0,0 +1,127 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel.catch" do
+ before :each do
+ ScratchPad.clear
+ end
+
+ it "executes its block and catches a thrown value matching its argument" do
+ catch :thrown_key do
+ ScratchPad.record :catch_block
+ throw :thrown_key
+ ScratchPad.record :throw_failed
+ end
+ ScratchPad.recorded.should == :catch_block
+ end
+
+ it "returns the second value passed to throw" do
+ catch(:thrown_key) { throw :thrown_key, :catch_value }.should == :catch_value
+ end
+
+ it "returns the last expression evaluated if throw was not called" do
+ catch(:thrown_key) { 1; :catch_block }.should == :catch_block
+ end
+
+ it "passes the given symbol to its block" do
+ catch :thrown_key do |tag|
+ ScratchPad.record tag
+ end
+ ScratchPad.recorded.should == :thrown_key
+ end
+
+ it "raises an ArgumentError if a Symbol is thrown for a String catch value" do
+ lambda { catch("exit") { throw :exit } }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if a String with different identity is thrown" do
+ lambda { catch("exit") { throw "exit" } }.should raise_error(ArgumentError)
+ end
+
+ it "catches a Symbol when thrown a matching Symbol" do
+ catch :thrown_key do
+ ScratchPad.record :catch_block
+ throw :thrown_key
+ end
+ ScratchPad.recorded.should == :catch_block
+ end
+
+ it "catches a String when thrown a String with the same identity" do
+ key = "thrown_key"
+ catch key do
+ ScratchPad.record :catch_block
+ throw key
+ end
+ ScratchPad.recorded.should == :catch_block
+ end
+
+ it "accepts an object as an argument" do
+ catch(Object.new) { :catch_block }.should == :catch_block
+ end
+
+ it "yields an object when called without arguments" do
+ catch { |tag| tag }.should be_an_instance_of(Object)
+ end
+
+ it "can be used even in a method different from where throw is called" do
+ class CatchSpecs
+ def self.throwing_method
+ throw :blah, :thrown_value
+ end
+ def self.catching_method
+ catch :blah do
+ throwing_method
+ end
+ end
+ end
+ CatchSpecs.catching_method.should == :thrown_value
+ end
+
+ describe "when nested" do
+ before :each do
+ ScratchPad.record []
+ end
+
+ it "catches across invocation boundaries" do
+ catch :one do
+ ScratchPad << 1
+ catch :two do
+ ScratchPad << 2
+ catch :three do
+ ScratchPad << 3
+ throw :one
+ ScratchPad << 4
+ end
+ ScratchPad << 5
+ end
+ ScratchPad << 6
+ end
+
+ ScratchPad.recorded.should == [1, 2, 3]
+ end
+
+ it "catches in the nested invocation with the same key object" do
+ catch :thrown_key do
+ ScratchPad << 1
+ catch :thrown_key do
+ ScratchPad << 2
+ throw :thrown_key
+ ScratchPad << 3
+ end
+ ScratchPad << 4
+ end
+
+ ScratchPad.recorded.should == [1, 2, 4]
+ end
+ end
+
+ it "raises LocalJumpError if no block is given" do
+ lambda { catch :blah }.should raise_error(LocalJumpError)
+ end
+end
+
+describe "Kernel#catch" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:catch)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/chomp_spec.rb b/spec/rubyspec/core/kernel/chomp_spec.rb
new file mode 100644
index 0000000000..4b34784169
--- /dev/null
+++ b/spec/rubyspec/core/kernel/chomp_spec.rb
@@ -0,0 +1,67 @@
+# -*- encoding: utf-8 -*-
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe :kernel_chomp, shared: true do
+ it "removes the final newline of $_" do
+ KernelSpecs.chomp("abc\n", @method).should == "abc"
+ end
+
+ it "removes the final carriage return of $_" do
+ KernelSpecs.chomp("abc\r", @method).should == "abc"
+ end
+
+ it "removes the final carriage return, newline of $_" do
+ KernelSpecs.chomp("abc\r\n", @method).should == "abc"
+ end
+
+ it "removes only the final newline of $_" do
+ KernelSpecs.chomp("abc\n\n", @method).should == "abc\n"
+ end
+
+ it "removes the value of $/ from the end of $_" do
+ KernelSpecs.chomp("abcde", @method, "cde").should == "ab"
+ end
+end
+
+describe :kernel_chomp_private, shared: true do
+ it "is a private method" do
+ KernelSpecs.has_private_method(@method).should be_true
+ end
+end
+
+describe "Kernel.chomp" do
+ it_behaves_like :kernel_chomp, "Kernel.chomp"
+end
+
+describe "Kernel#chomp" do
+ it_behaves_like :kernel_chomp, "chomp"
+
+ it_behaves_like :kernel_chomp_private, :chomp
+end
+
+with_feature :encoding do
+ describe :kernel_chomp_encoded, shared: true do
+ before :each do
+ @external = Encoding.default_external
+ Encoding.default_external = Encoding::UTF_8
+ end
+
+ after :each do
+ Encoding.default_external = @external
+ end
+
+ it "removes the final carriage return, newline from a multi-byte $_" do
+ script = fixture __FILE__, "#{@method}.rb"
+ KernelSpecs.encoded_chomp(script).should == "あれ"
+ end
+ end
+
+ describe "Kernel.chomp" do
+ it_behaves_like :kernel_chomp_encoded, "chomp"
+ end
+
+ describe "Kernel#chomp" do
+ it_behaves_like :kernel_chomp_encoded, "chomp_f"
+ end
+end
diff --git a/spec/rubyspec/core/kernel/chop_spec.rb b/spec/rubyspec/core/kernel/chop_spec.rb
new file mode 100644
index 0000000000..53b6e47cd1
--- /dev/null
+++ b/spec/rubyspec/core/kernel/chop_spec.rb
@@ -0,0 +1,55 @@
+# -*- encoding: utf-8 -*-
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe :kernel_chop, shared: true do
+ it "removes the final character of $_" do
+ KernelSpecs.chop("abc", @method).should == "ab"
+ end
+
+ it "removes the final carriage return, newline of $_" do
+ KernelSpecs.chop("abc\r\n", @method).should == "abc"
+ end
+end
+
+describe :kernel_chop_private, shared: true do
+ it "is a private method" do
+ KernelSpecs.has_private_method(@method).should be_true
+ end
+end
+
+describe "Kernel.chop" do
+ it_behaves_like :kernel_chop, "Kernel.chop"
+end
+
+describe "Kernel#chop" do
+ it_behaves_like :kernel_chop_private, :chop
+
+ it_behaves_like :kernel_chop, "chop"
+end
+
+with_feature :encoding do
+ describe :kernel_chop_encoded, shared: true do
+ before :each do
+ @external = Encoding.default_external
+ Encoding.default_external = Encoding::UTF_8
+ end
+
+ after :each do
+ Encoding.default_external = @external
+ end
+
+ it "removes the final multi-byte character from $_" do
+ script = fixture __FILE__, "#{@method}.rb"
+ KernelSpecs.encoded_chop(script).should == "あ"
+ end
+ end
+
+ describe "Kernel.chop" do
+ it_behaves_like :kernel_chop_encoded, "chop"
+ end
+
+ describe "Kernel#chop" do
+ it_behaves_like :kernel_chop_encoded, "chop_f"
+ end
+end
diff --git a/spec/rubyspec/core/kernel/class_spec.rb b/spec/rubyspec/core/kernel/class_spec.rb
new file mode 100644
index 0000000000..0d7b40c366
--- /dev/null
+++ b/spec/rubyspec/core/kernel/class_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#class" do
+ it "returns the class of the object" do
+ Object.new.class.should equal(Object)
+
+ 1.class.should equal(Fixnum)
+ 3.14.class.should equal(Float)
+ :hello.class.should equal(Symbol)
+ "hello".class.should equal(String)
+ [1, 2].class.should equal(Array)
+ { 1 => 2 }.class.should equal(Hash)
+ end
+
+ it "returns Class for a class" do
+ BasicObject.class.should equal(Class)
+ String.class.should equal(Class)
+ end
+
+ it "returns the first non-singleton class" do
+ a = "hello"
+ def a.my_singleton_method; end
+ a.class.should equal(String)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/clone_spec.rb b/spec/rubyspec/core/kernel/clone_spec.rb
new file mode 100644
index 0000000000..0e8216d434
--- /dev/null
+++ b/spec/rubyspec/core/kernel/clone_spec.rb
@@ -0,0 +1,108 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/dup_clone', __FILE__)
+
+describe "Kernel#clone" do
+ it_behaves_like :kernel_dup_clone, :clone
+
+ before :each do
+ ScratchPad.clear
+ @obj = KernelSpecs::Duplicate.new 1, :a
+ end
+
+ it "calls #initialize_copy on the new instance" do
+ clone = @obj.clone
+ ScratchPad.recorded.should_not == @obj.object_id
+ ScratchPad.recorded.should == clone.object_id
+ end
+
+ it "uses the internal allocator and does not call #allocate" do
+ klass = Class.new
+ instance = klass.new
+
+ def klass.allocate
+ raise "allocate should not be called"
+ end
+
+ clone = instance.clone
+ clone.class.should equal klass
+ end
+
+ it "copies frozen state from the original" do
+ o2 = @obj.clone
+ @obj.freeze
+ o3 = @obj.clone
+
+ o2.frozen?.should == false
+ o3.frozen?.should == true
+ end
+
+ it "copies instance variables" do
+ clone = @obj.clone
+ clone.one.should == 1
+ clone.two.should == :a
+ end
+
+ it "copies singleton methods" do
+ def @obj.special() :the_one end
+ clone = @obj.clone
+ clone.special.should == :the_one
+ end
+
+ it "copies modules included in the singleton class" do
+ class << @obj
+ include KernelSpecs::DuplicateM
+ end
+
+ clone = @obj.clone
+ clone.repr.should == "KernelSpecs::Duplicate"
+ end
+
+ it "copies constants defined in the singleton class" do
+ class << @obj
+ CLONE = :clone
+ end
+
+ clone = @obj.clone
+ class << clone
+ CLONE.should == :clone
+ end
+ end
+
+ it "replaces a singleton object's metaclass with a new copy with the same superclass" do
+ cls = Class.new do
+ def bar
+ ['a']
+ end
+ end
+
+ object = cls.new
+ object.define_singleton_method(:bar) do
+ ['b', *super()]
+ end
+ object.bar.should == ['b', 'a']
+
+ cloned = object.clone
+
+ cloned.singleton_methods.should == [:bar]
+
+ # bar should replace previous one
+ cloned.define_singleton_method(:bar) do
+ ['c', *super()]
+ end
+ cloned.bar.should == ['c', 'a']
+
+ # bar should be removed and call through to superclass
+ cloned.singleton_class.class_eval do
+ remove_method :bar
+ end
+
+ cloned.bar.should == ['a']
+ end
+
+ it 'copies frozen? and tainted?' do
+ o = ''.taint.freeze.clone
+ o.frozen?.should be_true
+ o.tainted?.should be_true
+ end
+end
diff --git a/spec/rubyspec/core/kernel/comparison_spec.rb b/spec/rubyspec/core/kernel/comparison_spec.rb
new file mode 100644
index 0000000000..2aa4358600
--- /dev/null
+++ b/spec/rubyspec/core/kernel/comparison_spec.rb
@@ -0,0 +1,31 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Kernel#<=>" do
+ it "returns 0 if self" do
+ obj = Object.new
+ obj.<=>(obj).should == 0
+ end
+
+ it "returns 0 if self is == to the argument" do
+ obj = mock('has ==')
+ obj.should_receive(:==).and_return(true)
+ obj.<=>(Object.new).should == 0
+ end
+
+ it "returns nil if self is eql? but not == to the argument" do
+ obj = mock('has eql?')
+ obj.should_not_receive(:eql?)
+ obj.<=>(Object.new).should be_nil
+ end
+
+ it "returns nil if self.==(arg) returns nil" do
+ obj = mock('wrong ==')
+ obj.should_receive(:==).and_return(nil)
+ obj.<=>(Object.new).should be_nil
+ end
+
+ it "returns nil if self is not == to the argument" do
+ obj = Object.new
+ obj.<=>(3.14).should be_nil
+ end
+end
diff --git a/spec/rubyspec/core/kernel/define_singleton_method_spec.rb b/spec/rubyspec/core/kernel/define_singleton_method_spec.rb
new file mode 100644
index 0000000000..de6f7fc286
--- /dev/null
+++ b/spec/rubyspec/core/kernel/define_singleton_method_spec.rb
@@ -0,0 +1,101 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#define_singleton_method" do
+ describe "when given an UnboundMethod" do
+ class DefineSingletonMethodSpecClass
+ MY_CONST = 42
+ define_singleton_method(:another_test_method, self.method(:constants))
+ end
+
+ it "correctly calls the new method" do
+ klass = DefineSingletonMethodSpecClass
+ klass.another_test_method.should == klass.constants
+ end
+
+ it "adds the new method to the methods list" do
+ DefineSingletonMethodSpecClass.should have_method(:another_test_method)
+ end
+
+ it "defines any Child class method from any Parent's class methods" do
+ um = KernelSpecs::Parent.method(:parent_class_method).unbind
+ KernelSpecs::Child.send :define_singleton_method, :child_class_method, um
+ KernelSpecs::Child.child_class_method.should == :foo
+ lambda{KernelSpecs::Parent.child_class_method}.should raise_error(NoMethodError)
+ end
+
+ it "will raise when attempting to define an object's singleton method from another object's singleton method" do
+ other = KernelSpecs::Parent.new
+ p = KernelSpecs::Parent.new
+ class << p
+ def singleton_method
+ :single
+ end
+ end
+ um = p.method(:singleton_method).unbind
+ lambda{ other.send :define_singleton_method, :other_singleton_method, um }.should raise_error(TypeError)
+ end
+
+ end
+
+ it "defines a new method with the given name and the given block as body in self" do
+ class DefineSingletonMethodSpecClass
+ define_singleton_method(:block_test1) { self }
+ define_singleton_method(:block_test2, &lambda { self })
+ end
+
+ o = DefineSingletonMethodSpecClass
+ o.block_test1.should == o
+ o.block_test2.should == o
+ end
+
+ it "raises a TypeError when the given method is no Method/Proc" do
+ lambda {
+ Class.new { define_singleton_method(:test, "self") }
+ }.should raise_error(TypeError)
+
+ lambda {
+ Class.new { define_singleton_method(:test, 1234) }
+ }.should raise_error(TypeError)
+ end
+
+ it "defines a new singleton method for objects" do
+ obj = Object.new
+ obj.define_singleton_method(:test) { "world!" }
+ obj.test.should == "world!"
+ lambda {
+ Object.new.test
+ }.should raise_error(NoMethodError)
+ end
+
+ it "maintains the Proc's scope" do
+ class DefineMethodByProcClass
+ in_scope = true
+ method_proc = proc { in_scope }
+
+ define_singleton_method(:proc_test, &method_proc)
+ end
+
+ DefineMethodByProcClass.proc_test.should == true
+ end
+
+ it "raises an ArgumentError when no block is given" do
+ obj = Object.new
+ lambda {
+ obj.define_singleton_method(:test)
+ }.should raise_error(ArgumentError)
+ end
+
+ ruby_version_is "2.3" do
+ it "does not use the caller block when no block is given" do
+ o = Object.new
+ def o.define(name)
+ define_singleton_method(name)
+ end
+
+ lambda {
+ o.define(:foo) { raise "not used" }
+ }.should raise_error(ArgumentError)
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/display_spec.rb b/spec/rubyspec/core/kernel/display_spec.rb
new file mode 100644
index 0000000000..e771e14cdb
--- /dev/null
+++ b/spec/rubyspec/core/kernel/display_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#display" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/dup_spec.rb b/spec/rubyspec/core/kernel/dup_spec.rb
new file mode 100644
index 0000000000..af7e924a66
--- /dev/null
+++ b/spec/rubyspec/core/kernel/dup_spec.rb
@@ -0,0 +1,67 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/dup_clone', __FILE__)
+
+describe "Kernel#dup" do
+ it_behaves_like :kernel_dup_clone, :dup
+
+ before :each do
+ ScratchPad.clear
+ @obj = KernelSpecs::Duplicate.new 1, :a
+ end
+
+ it "calls #initialize_copy on the new instance" do
+ dup = @obj.dup
+ ScratchPad.recorded.should_not == @obj.object_id
+ ScratchPad.recorded.should == dup.object_id
+ end
+
+ it "uses the internal allocator and does not call #allocate" do
+ klass = Class.new
+ instance = klass.new
+
+ def klass.allocate
+ raise "allocate should not be called"
+ end
+
+ dup = instance.dup
+ dup.class.should equal klass
+ end
+
+ it "does not copy frozen state from the original" do
+ @obj.freeze
+ dup = @obj.dup
+
+ dup.frozen?.should == false
+ end
+
+ it "copies instance variables" do
+ dup = @obj.dup
+ dup.one.should == 1
+ dup.two.should == :a
+ end
+
+ it "does not copy singleton methods" do
+ def @obj.special() :the_one end
+ dup = @obj.dup
+ lambda { dup.special }.should raise_error(NameError)
+ end
+
+ it "does not copy modules included in the singleton class" do
+ class << @obj
+ include KernelSpecs::DuplicateM
+ end
+
+ dup = @obj.dup
+ lambda { dup.repr }.should raise_error(NameError)
+ end
+
+ it "does not copy constants defined in the singleton class" do
+ class << @obj
+ CLONE = :clone
+ end
+
+ dup = @obj.dup
+ lambda { class << dup; CLONE; end }.should raise_error(NameError)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/enum_for_spec.rb b/spec/rubyspec/core/kernel/enum_for_spec.rb
new file mode 100644
index 0000000000..819140e0e4
--- /dev/null
+++ b/spec/rubyspec/core/kernel/enum_for_spec.rb
@@ -0,0 +1,5 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Kernel#enum_for" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/eql_spec.rb b/spec/rubyspec/core/kernel/eql_spec.rb
new file mode 100644
index 0000000000..39c9fea7eb
--- /dev/null
+++ b/spec/rubyspec/core/kernel/eql_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../../../shared/kernel/equal', __FILE__)
+
+describe "Kernel#eql?" do
+ it "is a public instance method" do
+ Kernel.should have_public_instance_method(:eql?)
+ end
+
+ it_behaves_like :object_equal, :eql?
+end
+
diff --git a/spec/rubyspec/core/kernel/equal_value_spec.rb b/spec/rubyspec/core/kernel/equal_value_spec.rb
new file mode 100644
index 0000000000..670987ead2
--- /dev/null
+++ b/spec/rubyspec/core/kernel/equal_value_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#==" do
+ it "returns true only if obj and other are the same object" do
+ o1 = mock('o1')
+ o2 = mock('o2')
+ (o1 == o1).should == true
+ (o2 == o2).should == true
+ (o1 == o2).should== false
+ (nil == nil).should == true
+ (o1 == nil).should== false
+ (nil == o2).should== false
+ end
+end
diff --git a/spec/rubyspec/core/kernel/eval_spec.rb b/spec/rubyspec/core/kernel/eval_spec.rb
new file mode 100644
index 0000000000..96fc0f5b71
--- /dev/null
+++ b/spec/rubyspec/core/kernel/eval_spec.rb
@@ -0,0 +1,216 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+EvalSpecs::A.new.c
+
+describe "Kernel#eval" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:eval)
+ end
+
+ it "is a module function" do
+ Kernel.respond_to?(:eval).should == true
+ end
+
+ it "evaluates the code within" do
+ eval("2 + 3").should == 5
+ end
+
+ it "coerces an object to string" do
+ eval(EvalSpecs::CoercedObject.new).should == 5
+ end
+
+ it "evaluates within the scope of the eval" do
+ EvalSpecs::A::B.name.should == "EvalSpecs::A::B"
+ end
+
+ it "evaluates such that consts are scoped to the class of the eval" do
+ EvalSpecs::A::C.name.should == "EvalSpecs::A::C"
+ end
+
+ it "finds a local in an enclosing scope" do
+ a = 1
+ eval("a").should == 1
+ end
+
+ it "updates a local in an enclosing scope" do
+ a = 1
+ eval("a = 2")
+ a.should == 2
+ end
+
+ it "updates a local in a surrounding block scope" do
+ EvalSpecs.new.f do
+ a = 1
+ eval("a = 2")
+ a.should == 2
+ end
+ end
+
+ it "updates a local in a scope above a surrounding block scope" do
+ a = 1
+ EvalSpecs.new.f do
+ eval("a = 2")
+ a.should == 2
+ end
+ a.should == 2
+ end
+
+ it "updates a local in a scope above when modified in a nested block scope" do
+ a = 1
+ es = EvalSpecs.new
+ eval("es.f { es.f { a = 2 } }")
+ a.should == 2
+ end
+
+ it "finds locals in a nested eval" do
+ eval('test = 10; eval("test")').should == 10
+ end
+
+ it "does not share locals across eval scopes" do
+ code = fixture __FILE__, "eval_locals.rb"
+ ruby_exe(code).chomp.should == "NameError"
+ end
+
+ it "doesn't accept a Proc object as a binding" do
+ x = 1
+ bind = proc {}
+
+ lambda { eval("x", bind) }.should raise_error(TypeError)
+ end
+
+ it "does not make Proc locals visible to evaluated code" do
+ bind = proc { inner = 4 }
+ lambda { eval("inner", bind.binding) }.should raise_error(NameError)
+ end
+
+ # REWRITE ME: This obscures the real behavior of where locals are stored
+ # in eval bindings.
+ it "allows a binding to be captured inside an eval" do
+ outer_binding = binding
+ level1 = eval("binding", outer_binding)
+ level2 = eval("binding", level1)
+
+ eval("x = 2", outer_binding)
+ eval("y = 3", level1)
+
+ eval("w=1", outer_binding)
+ eval("w", outer_binding).should == 1
+ eval("w=1", level1).should == 1
+ eval("w", level1).should == 1
+ eval("w=1", level2).should == 1
+ eval("w", level2).should == 1
+
+ eval("x", outer_binding).should == 2
+ eval("x=2", level1)
+ eval("x", level1).should == 2
+ eval("x=2", level2)
+ eval("x", level2).should == 2
+
+ eval("y=3", outer_binding)
+ eval("y", outer_binding).should == 3
+ eval("y=3", level1)
+ eval("y", level1).should == 3
+ eval("y=3", level2)
+ eval("y", level2).should == 3
+ end
+
+ it "uses the same scope for local variables when given the same binding" do
+ outer_binding = binding
+
+ eval("if false; a = 1; end", outer_binding)
+ eval("a", outer_binding).should be_nil
+ end
+
+ it "allows creating a new class in a binding" do
+ bind = proc {}
+ eval("class EvalBindingProcA; end; EvalBindingProcA.name", bind.binding).should =~ /EvalBindingProcA$/
+ end
+
+ it "allows creating a new class in a binding created by #eval" do
+ bind = eval "binding"
+ eval("class EvalBindingA; end; EvalBindingA.name", bind).should =~ /EvalBindingA$/
+ end
+
+ it "includes file and line information in syntax error" do
+ expected = 'speccing.rb'
+ lambda {
+ eval('if true',TOPLEVEL_BINDING, expected)
+ }.should raise_error(SyntaxError) { |e|
+ e.message.should =~ /#{expected}:1:.+/
+ }
+ end
+
+ it "evaluates string with given filename and negative linenumber" do
+ expected_file = 'speccing.rb'
+ lambda {
+ eval('if true',TOPLEVEL_BINDING, expected_file, -100)
+ }.should raise_error(SyntaxError) { |e|
+ e.message.should =~ /#{expected_file}:-100:.+/
+ }
+ end
+
+ it "sets constants at the toplevel from inside a block" do
+ # The class Object bit is needed to workaround some mspec oddness
+ class Object
+ [1].each { eval "Const = 1"}
+ Const.should == 1
+ remove_const :Const
+ end
+ end
+
+ it "uses the filename of the binding if none is provided" do
+ eval("__FILE__").should == "(eval)"
+ eval("__FILE__", binding).should == __FILE__
+ eval("__FILE__", binding, "success").should == "success"
+ eval("eval '__FILE__', binding").should == "(eval)"
+ eval("eval '__FILE__', binding", binding).should == __FILE__
+ eval("eval '__FILE__', binding", binding, 'success').should == 'success'
+ end
+
+ # Found via Rubinius bug github:#149
+ it "does not alter the value of __FILE__ in the binding" do
+ first_time = EvalSpecs.call_eval
+ second_time = EvalSpecs.call_eval
+
+ # This bug is seen by calling the method twice and comparing the values
+ # of __FILE__ each time. If the bug is present, calling eval will set the
+ # value of __FILE__ to the eval's "filename" argument.
+
+ second_time.should_not == "(eval)"
+ first_time.should == second_time
+ end
+
+ it "can be aliased" do
+ alias aliased_eval eval
+ x = 2
+ aliased_eval('x += 40')
+ x.should == 42
+ end
+
+ # See http://jira.codehaus.org/browse/JRUBY-5163
+ it "uses the receiver as self inside the eval" do
+ eval("self").should equal(self)
+ Kernel.eval("self").should equal(Kernel)
+ end
+
+ it "does not pass the block to the method being eval'ed" do
+ lambda {
+ eval('KernelSpecs::EvalTest.call_yield') { "content" }
+ }.should raise_error(LocalJumpError)
+ end
+
+ it "returns from the scope calling #eval when evaluating 'return'" do
+ lambda { eval("return :eval") }.call.should == :eval
+ end
+
+ it "unwinds through a Proc-style closure and returns from a lambda-style closure in the closure chain" do
+ code = fixture __FILE__, "eval_return_with_lambda.rb"
+ ruby_exe(code).chomp.should == "a,b,c,eval,f"
+ end
+
+ it "raises a LocalJumpError if there is no lambda-style closure in the chain" do
+ code = fixture __FILE__, "eval_return_without_lambda.rb"
+ ruby_exe(code).chomp.should == "a,b,c,e,LocalJumpError,f"
+ end
+end
diff --git a/spec/rubyspec/core/kernel/exec_spec.rb b/spec/rubyspec/core/kernel/exec_spec.rb
new file mode 100644
index 0000000000..3a7b656914
--- /dev/null
+++ b/spec/rubyspec/core/kernel/exec_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#exec" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:exec)
+ end
+
+ it "runs the specified command, replacing current process" do
+ ruby_exe('exec "echo hello"; puts "fail"', escape: true).should == "hello\n"
+ end
+end
+
+describe "Kernel.exec" do
+ it "runs the specified command, replacing current process" do
+ ruby_exe('Kernel.exec "echo hello"; puts "fail"', escape: true).should == "hello\n"
+ end
+end
diff --git a/spec/rubyspec/core/kernel/exit_spec.rb b/spec/rubyspec/core/kernel/exit_spec.rb
new file mode 100644
index 0000000000..5e175d5036
--- /dev/null
+++ b/spec/rubyspec/core/kernel/exit_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../../../shared/process/exit', __FILE__)
+
+describe "Kernel#exit" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:exit)
+ end
+
+ it_behaves_like :process_exit, :exit, KernelSpecs::Method.new
+end
+
+describe "Kernel#exit!" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:exit!)
+ end
+
+ it_behaves_like :process_exit!, :exit!, KernelSpecs::Method.new
+end
+
+describe "Kernel.exit" do
+ it_behaves_like :process_exit, :exit, Kernel
+end
+
+describe "Kernel.exit!" do
+ it_behaves_like :process_exit!, :exit!, Kernel
+end
diff --git a/spec/rubyspec/core/kernel/extend_spec.rb b/spec/rubyspec/core/kernel/extend_spec.rb
new file mode 100644
index 0000000000..482eef32e9
--- /dev/null
+++ b/spec/rubyspec/core/kernel/extend_spec.rb
@@ -0,0 +1,79 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+module KernelSpecs::M
+ def self.extend_object(o)
+ ScratchPad << "extend_object"
+ super
+ end
+
+ def self.extended(o)
+ ScratchPad << "extended"
+ super
+ end
+
+ def self.append_features(o)
+ ScratchPad << "append_features"
+ super
+ end
+end
+
+describe "Kernel#extend" do
+ before :each do
+ ScratchPad.record []
+ end
+
+ it "requires multiple arguments" do
+ Object.new.method(:extend).arity.should < 0
+ end
+
+ it "calls extend_object on argument" do
+ o = mock('o')
+ o.extend KernelSpecs::M
+ ScratchPad.recorded.include?("extend_object").should == true
+ end
+
+ it "does not calls append_features on arguments metaclass" do
+ o = mock('o')
+ o.extend KernelSpecs::M
+ ScratchPad.recorded.include?("append_features").should == false
+ end
+
+ it "calls extended on argument" do
+ o = mock('o')
+ o.extend KernelSpecs::M
+ ScratchPad.recorded.include?("extended").should == true
+ end
+
+ it "makes the class a kind_of? the argument" do
+ class C
+ extend KernelSpecs::M
+ end
+ (C.kind_of? KernelSpecs::M).should == true
+ end
+
+ it "raises an ArgumentError when no arguments given" do
+ lambda { Object.new.extend }.should raise_error(ArgumentError)
+ end
+
+ it "raises a TypeError when the argument is not a Module" do
+ o = mock('o')
+ klass = Class.new
+ lambda { o.extend(klass) }.should raise_error(TypeError)
+ end
+
+ describe "on frozen instance" do
+ before :each do
+ @frozen = Object.new.freeze
+ @module = KernelSpecs::M
+ end
+
+ it "raises an ArgumentError when no arguments given" do
+ lambda { @frozen.extend }.should raise_error(ArgumentError)
+ end
+
+ it "raises a RuntimeError" do
+ lambda { @frozen.extend @module }.should raise_error(RuntimeError)
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/fail_spec.rb b/spec/rubyspec/core/kernel/fail_spec.rb
new file mode 100644
index 0000000000..9f3601c233
--- /dev/null
+++ b/spec/rubyspec/core/kernel/fail_spec.rb
@@ -0,0 +1,43 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel.fail" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:fail)
+ end
+
+ it "raises a RuntimeError" do
+ lambda { fail }.should raise_error(RuntimeError)
+ end
+
+ it "accepts an Object with an exception method returning an Exception" do
+ class Boring
+ def self.exception(msg)
+ StandardError.new msg
+ end
+ end
+ lambda { fail Boring, "..." }.should raise_error(StandardError)
+ end
+
+ it "instantiates the specified exception class" do
+ class LittleBunnyFooFoo < RuntimeError; end
+ lambda { fail LittleBunnyFooFoo }.should raise_error(LittleBunnyFooFoo)
+ end
+
+ it "uses the specified message" do
+ lambda {
+ begin
+ fail "the duck is not irish."
+ rescue => e
+ e.message.should == "the duck is not irish."
+ raise
+ else
+ raise Exception
+ end
+ }.should raise_error(RuntimeError)
+ end
+end
+
+describe "Kernel#fail" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/fixtures/__callee__.rb b/spec/rubyspec/core/kernel/fixtures/__callee__.rb
new file mode 100644
index 0000000000..7138dbc5aa
--- /dev/null
+++ b/spec/rubyspec/core/kernel/fixtures/__callee__.rb
@@ -0,0 +1,34 @@
+module KernelSpecs
+ class CalleeTest
+ def f
+ __callee__
+ end
+
+ alias_method :g, :f
+
+ def in_block
+ (1..2).map { __callee__ }
+ end
+
+ define_method(:dm) do
+ __callee__
+ end
+
+ define_method(:dm_block) do
+ (1..2).map { __callee__ }
+ end
+
+ def from_send
+ send "__callee__"
+ end
+
+ def from_eval
+ eval "__callee__"
+ end
+
+ @@method = __callee__
+ def from_class_body
+ @@method
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/fixtures/__method__.rb b/spec/rubyspec/core/kernel/fixtures/__method__.rb
new file mode 100644
index 0000000000..9300366b37
--- /dev/null
+++ b/spec/rubyspec/core/kernel/fixtures/__method__.rb
@@ -0,0 +1,34 @@
+module KernelSpecs
+ class MethodTest
+ def f
+ __method__
+ end
+
+ alias_method :g, :f
+
+ def in_block
+ (1..2).map { __method__ }
+ end
+
+ define_method(:dm) do
+ __method__
+ end
+
+ define_method(:dm_block) do
+ (1..2).map { __method__ }
+ end
+
+ def from_send
+ send "__method__"
+ end
+
+ def from_eval
+ eval "__method__"
+ end
+
+ @@method = __method__
+ def from_class_body
+ @@method
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/fixtures/autoload_b.rb b/spec/rubyspec/core/kernel/fixtures/autoload_b.rb
new file mode 100644
index 0000000000..e8be221ec7
--- /dev/null
+++ b/spec/rubyspec/core/kernel/fixtures/autoload_b.rb
@@ -0,0 +1,5 @@
+module KSAutoloadB
+ def self.loaded
+ :ksautoload_b
+ end
+end
diff --git a/spec/rubyspec/core/kernel/fixtures/autoload_c.rb b/spec/rubyspec/core/kernel/fixtures/autoload_c.rb
new file mode 100644
index 0000000000..4569b23669
--- /dev/null
+++ b/spec/rubyspec/core/kernel/fixtures/autoload_c.rb
@@ -0,0 +1,5 @@
+module KSAutoloadC
+ def self.loaded
+ :ksautoload_c
+ end
+end
diff --git a/spec/rubyspec/core/kernel/fixtures/autoload_d.rb b/spec/rubyspec/core/kernel/fixtures/autoload_d.rb
new file mode 100644
index 0000000000..552cb5e82c
--- /dev/null
+++ b/spec/rubyspec/core/kernel/fixtures/autoload_d.rb
@@ -0,0 +1,5 @@
+module KSAutoloadD
+ def self.loaded
+ :ksautoload_d
+ end
+end
diff --git a/spec/rubyspec/core/kernel/fixtures/autoload_frozen.rb b/spec/rubyspec/core/kernel/fixtures/autoload_frozen.rb
new file mode 100644
index 0000000000..e9dc42912b
--- /dev/null
+++ b/spec/rubyspec/core/kernel/fixtures/autoload_frozen.rb
@@ -0,0 +1,7 @@
+Object.freeze
+
+begin
+ autoload :ANY_CONSTANT, "no_autoload.rb"
+rescue Exception => e
+ print e.class, " - ", defined?(ANY_CONSTANT).inspect
+end
diff --git a/spec/rubyspec/core/kernel/fixtures/caller.rb b/spec/rubyspec/core/kernel/fixtures/caller.rb
new file mode 100644
index 0000000000..ae3e13e9c9
--- /dev/null
+++ b/spec/rubyspec/core/kernel/fixtures/caller.rb
@@ -0,0 +1,7 @@
+module KernelSpecs
+ class CallerTest
+ def self.locations(*args)
+ caller(*args)
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/fixtures/caller_locations.rb b/spec/rubyspec/core/kernel/fixtures/caller_locations.rb
new file mode 100644
index 0000000000..cc4e04d38f
--- /dev/null
+++ b/spec/rubyspec/core/kernel/fixtures/caller_locations.rb
@@ -0,0 +1,7 @@
+module KernelSpecs
+ class CallerLocationsTest
+ def self.locations(*args)
+ caller_locations(*args)
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/fixtures/chomp.rb b/spec/rubyspec/core/kernel/fixtures/chomp.rb
new file mode 100644
index 0000000000..f08dbadce5
--- /dev/null
+++ b/spec/rubyspec/core/kernel/fixtures/chomp.rb
@@ -0,0 +1,4 @@
+# -*- encoding: utf-8 -*-
+
+$_ = "あれ\r\n"
+print Kernel.chomp
diff --git a/spec/rubyspec/core/kernel/fixtures/chomp_f.rb b/spec/rubyspec/core/kernel/fixtures/chomp_f.rb
new file mode 100644
index 0000000000..3c22cb21e7
--- /dev/null
+++ b/spec/rubyspec/core/kernel/fixtures/chomp_f.rb
@@ -0,0 +1,4 @@
+# -*- encoding: utf-8 -*-
+
+$_ = "あれ\r\n"
+print chomp
diff --git a/spec/rubyspec/core/kernel/fixtures/chop.rb b/spec/rubyspec/core/kernel/fixtures/chop.rb
new file mode 100644
index 0000000000..dfd0626723
--- /dev/null
+++ b/spec/rubyspec/core/kernel/fixtures/chop.rb
@@ -0,0 +1,4 @@
+# -*- encoding: utf-8 -*-
+
+$_ = "あれ"
+print Kernel.chop
diff --git a/spec/rubyspec/core/kernel/fixtures/chop_f.rb b/spec/rubyspec/core/kernel/fixtures/chop_f.rb
new file mode 100644
index 0000000000..4ec89eb9ec
--- /dev/null
+++ b/spec/rubyspec/core/kernel/fixtures/chop_f.rb
@@ -0,0 +1,4 @@
+# -*- encoding: utf-8 -*-
+
+$_ = "あれ"
+print chop
diff --git a/spec/rubyspec/core/kernel/fixtures/classes.rb b/spec/rubyspec/core/kernel/fixtures/classes.rb
new file mode 100644
index 0000000000..118b87fb8d
--- /dev/null
+++ b/spec/rubyspec/core/kernel/fixtures/classes.rb
@@ -0,0 +1,425 @@
+module KernelSpecs
+ def self.Array_function(arg)
+ Array(arg)
+ end
+
+ def self.Array_method(arg)
+ Kernel.Array(arg)
+ end
+
+ def self.Hash_function(arg)
+ Hash(arg)
+ end
+
+ def self.Hash_method(arg)
+ Kernel.Hash(arg)
+ end
+
+ def self.Integer_function(arg)
+ Integer(arg)
+ end
+
+ def self.Integer_method(arg)
+ Kernel.Integer(arg)
+ end
+
+ def self.putc_function(arg)
+ putc arg
+ end
+
+ def self.putc_method(arg)
+ Kernel.putc arg
+ end
+
+ def self.has_private_method(name)
+ cmd = %[| #{RUBY_EXE} -n -e "print Kernel.private_method_defined?('#{name}')"]
+ ruby_exe("puts", args: cmd) == "true"
+ end
+
+ def self.chop(str, method)
+ cmd = "| #{RUBY_EXE} -n -e '$_ = #{str.inspect}; #{method}; print $_'"
+ ruby_exe "puts", args: cmd
+ end
+
+ def self.encoded_chop(file)
+ ruby_exe "puts", args: "| #{RUBY_EXE} -n #{file}"
+ end
+
+ def self.chomp(str, method, sep="\n")
+ cmd = "| #{RUBY_EXE} -n -e '$_ = #{str.inspect}; $/ = #{sep.inspect}; #{method}; print $_'"
+ ruby_exe "puts", args: cmd
+ end
+
+ def self.encoded_chomp(file)
+ ruby_exe "puts", args: "| #{RUBY_EXE} -n #{file}"
+ end
+
+ # kind_of?, is_a?, instance_of?
+ module SomeOtherModule; end
+ module AncestorModule; end
+ module MyModule; end
+ module MyExtensionModule; end
+
+ class AncestorClass < String
+ include AncestorModule
+ end
+
+ class InstanceClass < AncestorClass
+ include MyModule
+ end
+
+ class KindaClass < AncestorClass
+ include MyModule
+ def initialize
+ self.extend MyExtensionModule
+ end
+ end
+
+ class Method
+ public :abort, :exit, :exit!, :fork, :system
+ end
+
+ class Methods
+
+ module MetaclassMethods
+ def peekaboo
+ end
+
+ protected
+
+ def nopeeking
+ end
+
+ private
+
+ def shoo
+ end
+ end
+
+ def self.ichi; end
+ def ni; end
+ class << self
+ def san; end
+ end
+
+ private
+
+ def self.shi; end
+ def juu_shi; end
+
+ class << self
+ def roku; end
+
+ private
+
+ def shichi; end
+ end
+
+ protected
+
+ def self.hachi; end
+ def ku; end
+
+ class << self
+ def juu; end
+
+ protected
+
+ def juu_ichi; end
+ end
+
+ public
+
+ def self.juu_ni; end
+ def juu_san; end
+ end
+
+ class PrivateSup
+ def public_in_sub
+ end
+
+ private :public_in_sub
+ end
+
+ class PublicSub < PrivateSup
+ def public_in_sub
+ end
+ end
+
+ class A
+ # There is Kernel#public_method, so we don't want this one to clash
+ def pub_method; :public_method; end
+
+ def undefed_method; :undefed_method; end
+ undef_method :undefed_method
+
+ protected
+ def protected_method; :protected_method; end
+
+ private
+ def private_method; :private_method; end
+
+ public
+ define_method(:defined_method) { :defined }
+ end
+
+ class B < A
+ alias aliased_pub_method pub_method
+ end
+
+ class VisibilityChange
+ class << self
+ private :new
+ end
+ end
+
+ class Binding
+ @@super_secret = "password"
+
+ def initialize(n)
+ @secret = n
+ end
+
+ def square(n)
+ n * n
+ end
+
+ def get_binding
+ a = true
+ @bind = binding
+
+ # Add/Change stuff
+ b = true
+ @secret += 1
+
+ @bind
+ end
+ end
+
+
+ module BlockGiven
+ def self.accept_block
+ block_given?
+ end
+
+ def self.accept_block_as_argument(&block)
+ block_given?
+ end
+
+ class << self
+ define_method(:defined_block) do
+ block_given?
+ end
+ end
+ end
+
+ module KernelBlockGiven
+ def self.accept_block
+ Kernel.block_given?
+ end
+
+ def self.accept_block_as_argument(&block)
+ Kernel.block_given?
+ end
+
+ class << self
+ define_method(:defined_block) do
+ Kernel.block_given?
+ end
+ end
+ end
+
+ module SelfBlockGiven
+ def self.accept_block
+ self.send(:block_given?)
+ end
+
+ def self.accept_block_as_argument(&block)
+ self.send(:block_given?)
+ end
+
+ class << self
+ define_method(:defined_block) do
+ self.send(:block_given?)
+ end
+ end
+ end
+
+ module KernelBlockGiven
+ def self.accept_block
+ Kernel.block_given?
+ end
+
+ def self.accept_block_as_argument(&block)
+ Kernel.block_given?
+ end
+
+ class << self
+ define_method(:defined_block) do
+ Kernel.block_given?
+ end
+ end
+ end
+
+ class EvalTest
+ def self.eval_yield_with_binding
+ eval("yield", binding)
+ end
+ def self.call_yield
+ yield
+ end
+ end
+
+ module DuplicateM
+ def repr
+ self.class.name.to_s
+ end
+ end
+
+ class Duplicate
+ attr_accessor :one, :two
+
+ def initialize(one, two)
+ @one = one
+ @two = two
+ end
+
+ def initialize_copy(other)
+ ScratchPad.record object_id
+ end
+ end
+
+ class Clone
+ def initialize_clone(other)
+ ScratchPad.record other.object_id
+ end
+ end
+
+ class Dup
+ def initialize_dup(other)
+ ScratchPad.record other.object_id
+ end
+ end
+
+ module ParentMixin
+ def parent_mixin_method; end
+ end
+
+ class Parent
+ include ParentMixin
+ def parent_method; end
+ def another_parent_method; end
+ def self.parent_class_method; :foo; end
+ end
+
+ class Child < Parent
+ undef_method :parent_method
+ end
+
+ class Grandchild < Child
+ undef_method :parent_mixin_method
+ end
+
+ # for testing lambda
+ class Lambda
+ def outer
+ inner
+ end
+
+ def mp(&b); b; end
+
+ def inner
+ b = mp { return :good }
+
+ pr = lambda { |x| x.call }
+
+ pr.call(b)
+
+ # We shouldn't be here, b should have unwinded through
+ return :bad
+ end
+ end
+
+ class RespondViaMissing
+ def respond_to_missing?(method, priv=false)
+ case method
+ when :handled_publicly
+ true
+ when :handled_privately
+ priv
+ when :not_handled
+ false
+ else
+ raise "Typo in method name"
+ end
+ end
+
+ def method_missing(method, *args)
+ "Done #{method}(#{args})"
+ end
+ end
+
+ class InstanceVariable
+ def initialize
+ @greeting = "hello"
+ end
+ end
+
+ class PrivateToAry
+ private
+
+ def to_ary
+ [1, 2]
+ end
+
+ def to_a
+ [3, 4]
+ end
+ end
+
+ class PrivateToA
+ private
+
+ def to_a
+ [3, 4]
+ end
+ end
+end
+
+class EvalSpecs
+ class A
+ eval "class B; end"
+ def c
+ eval "class C; end"
+ end
+ end
+
+ class CoercedObject
+ def to_str
+ '2 + 3'
+ end
+
+ def hash
+ nil
+ end
+ end
+
+ def f
+ yield
+ end
+
+ def self.call_eval
+ f = __FILE__
+ eval "true", binding, "(eval)", 1
+ return f
+ end
+end
+
+# for Kernel#sleep to have Channel in it's specs
+# TODO: switch directly to queue for both Kernel#sleep and Thread specs?
+unless defined? Channel
+ require 'thread'
+ class Channel < Queue
+ alias receive shift
+ end
+end
diff --git a/spec/rubyspec/core/kernel/fixtures/eval_locals.rb b/spec/rubyspec/core/kernel/fixtures/eval_locals.rb
new file mode 100644
index 0000000000..ca8b381806
--- /dev/null
+++ b/spec/rubyspec/core/kernel/fixtures/eval_locals.rb
@@ -0,0 +1,6 @@
+begin
+ eval("a = 2")
+ eval("p a")
+rescue Object => e
+ puts e.class
+end
diff --git a/spec/rubyspec/core/kernel/fixtures/eval_return_with_lambda.rb b/spec/rubyspec/core/kernel/fixtures/eval_return_with_lambda.rb
new file mode 100644
index 0000000000..a48b5685f3
--- /dev/null
+++ b/spec/rubyspec/core/kernel/fixtures/eval_return_with_lambda.rb
@@ -0,0 +1,12 @@
+print "a,"
+x = lambda do
+ print "b,"
+ Proc.new do
+ print "c,"
+ eval("return :eval")
+ print "d,"
+ end.call
+ print "e,"
+end.call
+print x, ","
+print "f"
diff --git a/spec/rubyspec/core/kernel/fixtures/eval_return_without_lambda.rb b/spec/rubyspec/core/kernel/fixtures/eval_return_without_lambda.rb
new file mode 100644
index 0000000000..fc8b7f1d4a
--- /dev/null
+++ b/spec/rubyspec/core/kernel/fixtures/eval_return_without_lambda.rb
@@ -0,0 +1,14 @@
+print "a,"
+begin
+ print "b,"
+ x = Proc.new do
+ print "c,"
+ eval("return :eval")
+ print "d,"
+ end.call
+ print x, ","
+rescue LocalJumpError => e
+ print "e,"
+ print e.class, ","
+end
+print "f"
diff --git a/spec/rubyspec/core/kernel/fixtures/test.rb b/spec/rubyspec/core/kernel/fixtures/test.rb
new file mode 100644
index 0000000000..949948606f
--- /dev/null
+++ b/spec/rubyspec/core/kernel/fixtures/test.rb
@@ -0,0 +1,362 @@
+def foo1
+end
+
+def foo2
+end
+
+def foo3
+end
+
+def foo4
+end
+
+def foo5
+end
+
+def foo6
+end
+
+def foo7
+end
+
+def foo8
+end
+
+def foo9
+end
+
+def foo10
+end
+
+def foo11
+end
+
+def foo12
+end
+
+def foo13
+end
+
+def foo14
+end
+
+def foo15
+end
+
+def foo16
+end
+
+def foo17
+end
+
+def foo18
+end
+
+def foo19
+end
+
+def foo20
+end
+
+def foo21
+end
+
+def foo22
+end
+
+def foo23
+end
+
+def foo24
+end
+
+def foo25
+end
+
+def foo26
+end
+
+def foo27
+end
+
+def foo28
+end
+
+def foo29
+end
+
+def foo30
+end
+
+def foo31
+end
+
+def foo32
+end
+
+def foo33
+end
+
+def foo34
+end
+
+def foo35
+end
+
+def foo36
+end
+
+def foo37
+end
+
+def foo38
+end
+
+def foo39
+end
+
+def foo40
+end
+
+def foo41
+end
+
+def foo42
+end
+
+def foo43
+end
+
+def foo44
+end
+
+def foo45
+end
+
+def foo46
+end
+
+def foo47
+end
+
+def foo48
+end
+
+def foo49
+end
+
+def foo50
+end
+
+def foo51
+end
+
+def foo52
+end
+
+def foo53
+end
+
+def foo54
+end
+
+def foo55
+end
+
+def foo56
+end
+
+def foo57
+end
+
+def foo58
+end
+
+def foo59
+end
+
+def foo60
+end
+
+def foo61
+end
+
+def foo62
+end
+
+def foo63
+end
+
+def foo64
+end
+
+def foo65
+end
+
+def foo66
+end
+
+def foo67
+end
+
+def foo68
+end
+
+def foo69
+end
+
+def foo70
+end
+
+def foo71
+end
+
+def foo72
+end
+
+def foo73
+end
+
+def foo74
+end
+
+def foo75
+end
+
+def foo76
+end
+
+def foo77
+end
+
+def foo78
+end
+
+def foo79
+end
+
+def foo80
+end
+
+def foo81
+end
+
+def foo82
+end
+
+def foo83
+end
+
+def foo84
+end
+
+def foo85
+end
+
+def foo86
+end
+
+def foo87
+end
+
+def foo88
+end
+
+def foo89
+end
+
+def foo90
+end
+
+def foo91
+end
+
+def foo92
+end
+
+def foo93
+end
+
+def foo94
+end
+
+def foo95
+end
+
+def foo96
+end
+
+def foo97
+end
+
+def foo98
+end
+
+def foo99
+end
+
+def foo100
+end
+
+def foo101
+end
+
+def foo102
+end
+
+def foo103
+end
+
+def foo104
+end
+
+def foo105
+end
+
+def foo106
+end
+
+def foo107
+end
+
+def foo108
+end
+
+def foo109
+end
+
+def foo110
+end
+
+def foo111
+end
+
+def foo112
+end
+
+def foo113
+end
+
+def foo114
+end
+
+def foo115
+end
+
+def foo116
+end
+
+def foo117
+end
+
+def foo118
+end
+
+def foo119
+end
+
+def foo120
+end
+
+def foo121
+end
diff --git a/spec/rubyspec/core/kernel/fork_spec.rb b/spec/rubyspec/core/kernel/fork_spec.rb
new file mode 100644
index 0000000000..8919d0914d
--- /dev/null
+++ b/spec/rubyspec/core/kernel/fork_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../../../shared/process/fork', __FILE__)
+
+describe "Kernel#fork" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:fork)
+ end
+
+ it_behaves_like :process_fork, :fork, KernelSpecs::Method.new
+end
+
+describe "Kernel.fork" do
+ it_behaves_like :process_fork, :fork, Kernel
+end
diff --git a/spec/rubyspec/core/kernel/format_spec.rb b/spec/rubyspec/core/kernel/format_spec.rb
new file mode 100644
index 0000000000..c73d5f0efb
--- /dev/null
+++ b/spec/rubyspec/core/kernel/format_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#format" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:format)
+ end
+end
+
+describe "Kernel.format" do
+ it "is accessible as a module function" do
+ Kernel.format("%s", "hello").should == "hello"
+ end
+end
diff --git a/spec/rubyspec/core/kernel/freeze_spec.rb b/spec/rubyspec/core/kernel/freeze_spec.rb
new file mode 100644
index 0000000000..961c1bccf0
--- /dev/null
+++ b/spec/rubyspec/core/kernel/freeze_spec.rb
@@ -0,0 +1,67 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#freeze" do
+ it "prevents self from being further modified" do
+ o = mock('o')
+ o.frozen?.should be_false
+ o.freeze
+ o.frozen?.should be_true
+ end
+
+ it "returns self" do
+ o = Object.new
+ o.freeze.should equal(o)
+ end
+
+ describe "on integers" do
+ it "has no effect since they are already frozen" do
+ 1.frozen?.should be_true
+ 1.freeze
+
+ bignum = bignum_value
+ bignum.frozen?.should be_true
+ bignum.freeze
+ end
+ end
+
+ describe "on a Float" do
+ it "has no effect since it is already frozen" do
+ 1.2.frozen?.should be_true
+ 1.2.freeze
+ end
+ end
+
+ describe "on a Symbol" do
+ it "has no effect since it is already frozen" do
+ :sym.frozen?.should be_true
+ :sym.freeze
+ end
+ end
+
+ describe "on true, false and nil" do
+ it "has no effect since they are already frozen" do
+ nil.frozen?.should be_true
+ true.frozen?.should be_true
+ false.frozen?.should be_true
+
+ nil.freeze
+ true.freeze
+ false.freeze
+ end
+ end
+
+ it "causes mutative calls to raise RuntimeError" do
+ o = Class.new do
+ def mutate; @foo = 1; end
+ end.new
+ o.freeze
+ lambda {o.mutate}.should raise_error(RuntimeError)
+ end
+
+ it "causes instance_variable_set to raise RuntimeError" do
+ o = Object.new
+ o.freeze
+ lambda {o.instance_variable_set(:@foo, 1)}.should raise_error(RuntimeError)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/frozen_spec.rb b/spec/rubyspec/core/kernel/frozen_spec.rb
new file mode 100644
index 0000000000..9444b62249
--- /dev/null
+++ b/spec/rubyspec/core/kernel/frozen_spec.rb
@@ -0,0 +1,52 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#frozen?" do
+ it "returns true if self is frozen" do
+ o = mock('o')
+ p = mock('p')
+ p.freeze
+ o.frozen?.should == false
+ p.frozen?.should == true
+ end
+
+ describe "on true, false and nil" do
+ it "returns true" do
+ true.frozen?.should be_true
+ false.frozen?.should be_true
+ nil.frozen?.should be_true
+ end
+ end
+
+ describe "on integers" do
+ before :each do
+ @fixnum = 1
+ @bignum = bignum_value
+ end
+
+ it "returns true" do
+ @fixnum.frozen?.should be_true
+ @bignum.frozen?.should be_true
+ end
+ end
+
+ describe "on a Float" do
+ before :each do
+ @float = 0.1
+ end
+
+ it "returns true" do
+ @float.frozen?.should be_true
+ end
+ end
+
+ describe "on a Symbol" do
+ before :each do
+ @symbol = :symbol
+ end
+
+ it "returns true" do
+ @symbol.frozen?.should be_true
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/gets_spec.rb b/spec/rubyspec/core/kernel/gets_spec.rb
new file mode 100644
index 0000000000..eb68e093ab
--- /dev/null
+++ b/spec/rubyspec/core/kernel/gets_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#gets" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:gets)
+ end
+end
+
+describe "Kernel.gets" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/global_variables_spec.rb b/spec/rubyspec/core/kernel/global_variables_spec.rb
new file mode 100644
index 0000000000..739b800938
--- /dev/null
+++ b/spec/rubyspec/core/kernel/global_variables_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel.global_variables" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:global_variables)
+ end
+
+ before :all do
+ @i = 0
+ end
+
+ it "finds subset starting with std" do
+ global_variables.grep(/std/).should include(:$stderr, :$stdin, :$stdout)
+ a = global_variables.size
+ gvar_name = "$foolish_global_var#{@i += 1}"
+ global_variables.include?(gvar_name.to_sym).should == false
+ eval("#{gvar_name} = 1")
+ global_variables.size.should == a+1
+ global_variables.should include(gvar_name.to_sym)
+ end
+end
+
+describe "Kernel#global_variables" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/gsub_spec.rb b/spec/rubyspec/core/kernel/gsub_spec.rb
new file mode 100644
index 0000000000..005ed0063d
--- /dev/null
+++ b/spec/rubyspec/core/kernel/gsub_spec.rb
@@ -0,0 +1,96 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+# FIXME: These methods exist only when the -n or -p option is passed to
+# ruby, but we currently don't have a way of specifying that.
+ruby_version_is ""..."1.9" do
+ describe "Kernel#gsub" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:gsub)
+ end
+
+ it "raises a TypeError if $_ is not a String" do
+ lambda {
+ $_ = 123
+ gsub(/./, "!")
+ }.should raise_error(TypeError)
+ end
+
+ it "when matches sets $_ to a new string, leaving the former value unaltered" do
+ orig_value = $_ = "hello"
+ gsub("ello", "ola")
+ $_.should_not equal(orig_value)
+ $_.should == "hola"
+ orig_value.should == "hello"
+ end
+
+ it "returns a string with the same contents as $_ after the operation" do
+ $_ = "bye"
+ gsub("non-match", "?").should == "bye"
+
+ orig_value = $_ = "bye"
+ gsub(/$/, "!").should == "bye!"
+ orig_value.should == "bye"
+ end
+
+ it "accepts Regexps as patterns" do
+ $_ = "food"
+ gsub(/.$/, "l")
+ $_.should == "fool"
+ end
+
+ it "accepts Strings as patterns, treated literally" do
+ $_ = "hello, world."
+ gsub(".", "!")
+ $_.should == "hello, world!"
+ end
+
+ it "accepts objects which respond to #to_str as patterns and treats them as strings" do
+ $_ = "hello, world."
+ stringlike = mock(".")
+ stringlike.should_receive(:to_str).and_return(".")
+ gsub(stringlike, "!")
+ $_.should == "hello, world!"
+ end
+ end
+
+ describe "Kernel#gsub with a pattern and replacement" do
+ it "accepts strings for replacement" do
+ $_ = "hello"
+ gsub(/./, ".")
+ $_.should == "....."
+ end
+
+ it "accepts objects which respond to #to_str for replacement" do
+ o = mock("o")
+ o.should_receive(:to_str).and_return("o")
+ $_ = "ping"
+ gsub("i", o)
+ $_.should == "pong"
+ end
+
+ it "replaces \\1 sequences with the regexp's corresponding capture" do
+ $_ = "hello!"
+ gsub(/(.)(.)/, '\2\1')
+ $_.should == "ehll!o"
+ end
+ end
+
+ describe "Kernel#gsub with pattern and block" do
+ it "acts similarly to using $_.gsub" do
+ $_ = "olleh dlrow"
+ gsub(/(\w+)/){ $1.reverse }
+ $_.should == "hello world"
+ end
+ end
+
+ describe "Kernel#gsub!" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:gsub!)
+ end
+ end
+
+ describe "Kernel.gsub!" do
+ it "needs to be reviewed for spec completeness"
+ end
+end
diff --git a/spec/rubyspec/core/kernel/inspect_spec.rb b/spec/rubyspec/core/kernel/inspect_spec.rb
new file mode 100644
index 0000000000..92129ebbc5
--- /dev/null
+++ b/spec/rubyspec/core/kernel/inspect_spec.rb
@@ -0,0 +1,31 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#inspect" do
+ it "returns a String" do
+ Object.new.inspect.should be_an_instance_of(String)
+ end
+
+ it "returns a tainted string if self is tainted" do
+ Object.new.taint.inspect.tainted?.should be_true
+ end
+
+ it "returns an untrusted string if self is untrusted" do
+ Object.new.untrust.inspect.untrusted?.should be_true
+ end
+
+ it "does not call #to_s if it is defined" do
+ # We must use a bare Object here
+ obj = Object.new
+ inspected = obj.inspect
+
+ obj.stub!(:to_s).and_return("to_s'd")
+
+ obj.inspect.should == inspected
+ end
+
+ it "returns a String with the object class and object_id encoded" do
+ obj = Object.new
+ obj.inspect.should =~ /^#<Object:0x[0-9a-f]+>$/
+ end
+end
diff --git a/spec/rubyspec/core/kernel/instance_of_spec.rb b/spec/rubyspec/core/kernel/instance_of_spec.rb
new file mode 100644
index 0000000000..4801a1ff96
--- /dev/null
+++ b/spec/rubyspec/core/kernel/instance_of_spec.rb
@@ -0,0 +1,40 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe Kernel, "#instance_of?" do
+ before :each do
+ @o = KernelSpecs::InstanceClass.new
+ end
+
+ it "returns true if given class is object's class" do
+ @o.instance_of?(KernelSpecs::InstanceClass).should == true
+ [].instance_of?(Array).should == true
+ ''.instance_of?(String).should == true
+ end
+
+ it "returns false if given class is object's ancestor class" do
+ @o.instance_of?(KernelSpecs::AncestorClass).should == false
+ end
+
+ it "returns false if given class is not object's class nor object's ancestor class" do
+ @o.instance_of?(Array).should == false
+ end
+
+ it "returns false if given a Module that is included in object's class" do
+ @o.instance_of?(KernelSpecs::MyModule).should == false
+ end
+
+ it "returns false if given a Module that is included one of object's ancestors only" do
+ @o.instance_of?(KernelSpecs::AncestorModule).should == false
+ end
+
+ it "returns false if given a Module that is not included in object's class" do
+ @o.instance_of?(KernelSpecs::SomeOtherModule).should == false
+ end
+
+ it "raises a TypeError if given an object that is not a Class nor a Module" do
+ lambda { @o.instance_of?(Object.new) }.should raise_error(TypeError)
+ lambda { @o.instance_of?('KernelSpecs::InstanceClass') }.should raise_error(TypeError)
+ lambda { @o.instance_of?(1) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/instance_variable_defined_spec.rb b/spec/rubyspec/core/kernel/instance_variable_defined_spec.rb
new file mode 100644
index 0000000000..969d36c731
--- /dev/null
+++ b/spec/rubyspec/core/kernel/instance_variable_defined_spec.rb
@@ -0,0 +1,41 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#instance_variable_defined?" do
+ before do
+ @instance = KernelSpecs::InstanceVariable.new
+ end
+
+ describe "when passed a String" do
+ it "returns false if the instance variable is not defined" do
+ @instance.instance_variable_defined?("@goodbye").should be_false
+ end
+
+ it "returns true if the instance variable is defined" do
+ @instance.instance_variable_defined?("@greeting").should be_true
+ end
+ end
+
+ describe "when passed a Symbol" do
+ it "returns false if the instance variable is not defined" do
+ @instance.instance_variable_defined?(:@goodbye).should be_false
+ end
+
+ it "returns true if the instance variable is defined" do
+ @instance.instance_variable_defined?(:@greeting).should be_true
+ end
+ end
+
+ it "raises a TypeError if passed an Object not defining #to_str" do
+ lambda do
+ obj = mock("kernel instance_variable_defined?")
+ @instance.instance_variable_defined? obj
+ end.should raise_error(TypeError)
+ end
+
+ it "returns false if the instance variable is not defined for different types" do
+ [nil, false, true, 1, 2.0, :test, "test"].each do |obj|
+ obj.instance_variable_defined?("@goodbye").should be_false
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/instance_variable_get_spec.rb b/spec/rubyspec/core/kernel/instance_variable_get_spec.rb
new file mode 100644
index 0000000000..0c564f11b6
--- /dev/null
+++ b/spec/rubyspec/core/kernel/instance_variable_get_spec.rb
@@ -0,0 +1,105 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#instance_variable_get" do
+ before :each do
+ @obj = Object.new
+ @obj.instance_variable_set("@test", :test)
+ end
+
+ it "tries to convert the passed argument to a String using #to_str" do
+ obj = mock("to_str")
+ obj.should_receive(:to_str).and_return("@test")
+ @obj.instance_variable_get(obj)
+ end
+
+ it "returns the value of the passed instance variable that is referred to by the conversion result" do
+ obj = mock("to_str")
+ obj.stub!(:to_str).and_return("@test")
+ @obj.instance_variable_get(obj).should == :test
+ end
+
+ it "returns nil when the referred instance variable does not exist" do
+ @obj.instance_variable_get(:@does_not_exist).should be_nil
+ end
+
+ it "raises a TypeError when the passed argument does not respond to #to_str" do
+ lambda { @obj.instance_variable_get(Object.new) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError when the passed argument can't be converted to a String" do
+ obj = mock("to_str")
+ obj.stub!(:to_str).and_return(123)
+ lambda { @obj.instance_variable_get(obj) }.should raise_error(TypeError)
+ end
+
+ it "raises a NameError when the conversion result does not start with an '@'" do
+ obj = mock("to_str")
+ obj.stub!(:to_str).and_return("test")
+ lambda { @obj.instance_variable_get(obj) }.should raise_error(NameError)
+ end
+
+ it "raises a NameError when passed just '@'" do
+ obj = mock("to_str")
+ obj.stub!(:to_str).and_return('@')
+ lambda { @obj.instance_variable_get(obj) }.should raise_error(NameError)
+ end
+end
+
+describe "Kernel#instance_variable_get when passed Symbol" do
+ before :each do
+ @obj = Object.new
+ @obj.instance_variable_set("@test", :test)
+ end
+
+ it "returns the value of the instance variable that is referred to by the passed Symbol" do
+ @obj.instance_variable_get(:@test).should == :test
+ end
+
+ it "raises a NameError when passed :@ as an instance variable name" do
+ lambda { @obj.instance_variable_get(:"@") }.should raise_error(NameError)
+ end
+
+ it "raises a NameError when the passed Symbol does not start with an '@'" do
+ lambda { @obj.instance_variable_get(:test) }.should raise_error(NameError)
+ end
+
+ it "raises a NameError when the passed Symbol is an invalid instance variable name" do
+ lambda { @obj.instance_variable_get(:"@0") }.should raise_error(NameError)
+ end
+end
+
+describe "Kernel#instance_variable_get when passed String" do
+ before :each do
+ @obj = Object.new
+ @obj.instance_variable_set("@test", :test)
+ end
+
+ it "returns the value of the instance variable that is referred to by the passed String" do
+ @obj.instance_variable_get("@test").should == :test
+ end
+
+ it "raises a NameError when the passed String does not start with an '@'" do
+ lambda { @obj.instance_variable_get("test") }.should raise_error(NameError)
+ end
+
+ it "raises a NameError when the passed String is an invalid instance variable name" do
+ lambda { @obj.instance_variable_get("@0") }.should raise_error(NameError)
+ end
+
+ it "raises a NameError when passed '@' as an instance variable name" do
+ lambda { @obj.instance_variable_get("@") }.should raise_error(NameError)
+ end
+end
+
+describe "Kernel#instance_variable_get when passed Fixnum" do
+ before :each do
+ @obj = Object.new
+ @obj.instance_variable_set("@test", :test)
+ end
+
+ it "raises a TypeError" do
+ lambda { @obj.instance_variable_get(10) }.should raise_error(TypeError)
+ lambda { @obj.instance_variable_get(-10) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/instance_variable_set_spec.rb b/spec/rubyspec/core/kernel/instance_variable_set_spec.rb
new file mode 100644
index 0000000000..bac1bb5f99
--- /dev/null
+++ b/spec/rubyspec/core/kernel/instance_variable_set_spec.rb
@@ -0,0 +1,93 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#instance_variable_set" do
+ it "sets the value of the specified instance variable" do
+ class Dog
+ def initialize(p1, p2)
+ @a, @b = p1, p2
+ end
+ end
+ Dog.new('cat', 99).instance_variable_set(:@a, 'dog').should == "dog"
+ end
+
+ it "sets the value of the instance variable when no instance variables exist yet" do
+ class NoVariables; end
+ NoVariables.new.instance_variable_set(:@a, "new").should == "new"
+ end
+
+ it "raises a NameError exception if the argument is not of form '@x'" do
+ class NoDog; end
+ lambda { NoDog.new.instance_variable_set(:c, "cat") }.should raise_error(NameError)
+ end
+
+ it "raises a NameError exception if the argument is an invalid instance variable name" do
+ class DigitDog; end
+ lambda { DigitDog.new.instance_variable_set(:"@0", "cat") }.should raise_error(NameError)
+ end
+
+ it "raises a NameError when the argument is '@'" do
+ class DogAt; end
+ lambda { DogAt.new.instance_variable_set(:"@", "cat") }.should raise_error(NameError)
+ end
+
+ it "raises a TypeError if the instance variable name is a Fixnum" do
+ lambda { "".instance_variable_set(1, 2) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if the instance variable name is an object that does not respond to to_str" do
+ class KernelSpecs::A; end
+ lambda { "".instance_variable_set(KernelSpecs::A.new, 3) }.should raise_error(TypeError)
+ end
+
+ it "raises a NameError if the passed object, when coerced with to_str, does not start with @" do
+ class KernelSpecs::B
+ def to_str
+ ":c"
+ end
+ end
+ lambda { "".instance_variable_set(KernelSpecs::B.new, 4) }.should raise_error(NameError)
+ end
+
+ it "raises a NameError if pass an object that cannot be a symbol" do
+ lambda { "".instance_variable_set(:c, 1) }.should raise_error(NameError)
+ end
+
+ it "accepts as instance variable name any instance of a class that responds to to_str" do
+ class KernelSpecs::C
+ def initialize
+ @a = 1
+ end
+ def to_str
+ "@a"
+ end
+ end
+ KernelSpecs::C.new.instance_variable_set(KernelSpecs::C.new, 2).should == 2
+ end
+
+ describe "on frozen objects" do
+ before :each do
+ klass = Class.new do
+ attr_reader :ivar
+ def initialize
+ @ivar = :origin
+ end
+ end
+
+ @frozen = klass.new.freeze
+ end
+
+ it "keeps stored object after any exceptions" do
+ lambda { @frozen.instance_variable_set(:@ivar, :replacement) }.should raise_error(Exception)
+ @frozen.ivar.should equal(:origin)
+ end
+
+ it "raises a RuntimeError when passed replacement is identical to stored object" do
+ lambda { @frozen.instance_variable_set(:@ivar, :origin) }.should raise_error(RuntimeError)
+ end
+
+ it "raises a RuntimeError when passed replacement is different from stored object" do
+ lambda { @frozen.instance_variable_set(:@ivar, :replacement) }.should raise_error(RuntimeError)
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/instance_variables_spec.rb b/spec/rubyspec/core/kernel/instance_variables_spec.rb
new file mode 100644
index 0000000000..f744ee3c7a
--- /dev/null
+++ b/spec/rubyspec/core/kernel/instance_variables_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#instance_variables" do
+ describe "immediate values" do
+ it "returns an empty array if no instance variables are defined" do
+ 0.instance_variables.should == []
+ end
+
+ it "returns the correct array if an instance variable is added" do
+ a = 0
+ lambda{ a.instance_variable_set("@test", 1) }.should raise_error(RuntimeError)
+ end
+ end
+
+ describe "regular objects" do
+ it "returns an empty array if no instance variables are defined" do
+ Object.new.instance_variables.should == []
+ end
+
+ it "returns the correct array if an instance variable is added" do
+ a = Object.new
+ a.instance_variable_set("@test", 1)
+ a.instance_variables.should == [:@test]
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/is_a_spec.rb b/spec/rubyspec/core/kernel/is_a_spec.rb
new file mode 100644
index 0000000000..c67c6552a0
--- /dev/null
+++ b/spec/rubyspec/core/kernel/is_a_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/kind_of', __FILE__)
+
+describe "Kernel#is_a?" do
+ it_behaves_like(:kernel_kind_of , :is_a?)
+end
diff --git a/spec/rubyspec/core/kernel/iterator_spec.rb b/spec/rubyspec/core/kernel/iterator_spec.rb
new file mode 100644
index 0000000000..e85f0dc612
--- /dev/null
+++ b/spec/rubyspec/core/kernel/iterator_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#iterator?" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:iterator?)
+ end
+end
+
+describe "Kernel.iterator?" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/itself_spec.rb b/spec/rubyspec/core/kernel/itself_spec.rb
new file mode 100644
index 0000000000..285080ec3b
--- /dev/null
+++ b/spec/rubyspec/core/kernel/itself_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#itself" do
+ it "returns the receiver itself" do
+ foo = Object.new
+ foo.itself.should equal foo
+ foo.itself.object_id.should equal foo.object_id
+ end
+end
diff --git a/spec/rubyspec/core/kernel/kind_of_spec.rb b/spec/rubyspec/core/kernel/kind_of_spec.rb
new file mode 100644
index 0000000000..56a54ec859
--- /dev/null
+++ b/spec/rubyspec/core/kernel/kind_of_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/kind_of', __FILE__)
+
+describe "Kernel#kind_of?" do
+ it_behaves_like(:kernel_kind_of , :kind_of?)
+end
diff --git a/spec/rubyspec/core/kernel/lambda_spec.rb b/spec/rubyspec/core/kernel/lambda_spec.rb
new file mode 100644
index 0000000000..8fa0075675
--- /dev/null
+++ b/spec/rubyspec/core/kernel/lambda_spec.rb
@@ -0,0 +1,86 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/lambda', __FILE__)
+
+# The functionality of lambdas is specified in core/proc
+
+describe "Kernel.lambda" do
+ it_behaves_like(:kernel_lambda, :lambda)
+
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:lambda)
+ end
+
+ it "creates a lambda-style Proc if given a literal block" do
+ l = lambda { 42 }
+ l.lambda?.should be_true
+ end
+
+ it "returned the passed Proc if given an existing Proc" do
+ some_proc = proc {}
+ l = lambda(&some_proc)
+ l.should equal(some_proc)
+ l.lambda?.should be_false
+ end
+
+ it "checks the arity of the call when no args are specified" do
+ l = lambda { :called }
+ l.call.should == :called
+
+ lambda { l.call(1) }.should raise_error(ArgumentError)
+ lambda { l.call(1, 2) }.should raise_error(ArgumentError)
+ end
+
+ it "checks the arity when 1 arg is specified" do
+ l = lambda { |a| :called }
+ l.call(1).should == :called
+
+ lambda { l.call }.should raise_error(ArgumentError)
+ lambda { l.call(1, 2) }.should raise_error(ArgumentError)
+ end
+
+ it "does not check the arity when passing a Proc with &" do
+ l = lambda { || :called }
+ p = proc { || :called }
+
+ lambda { l.call(1) }.should raise_error(ArgumentError)
+ p.call(1).should == :called
+ end
+
+ it "accepts 0 arguments when used with ||" do
+ lambda {
+ lambda { || }.call(1)
+ }.should raise_error(ArgumentError)
+ end
+
+ it "strictly checks the arity when 0 or 2..inf args are specified" do
+ l = lambda { |a,b| }
+
+ lambda {
+ l.call
+ }.should raise_error(ArgumentError)
+
+ lambda {
+ l.call(1)
+ }.should raise_error(ArgumentError)
+
+ lambda {
+ l.call(1,2)
+ }.should_not raise_error(ArgumentError)
+ end
+
+ it "returns from the lambda itself, not the creation site of the lambda" do
+ @reached_end_of_method = nil
+ def test
+ send(:lambda) { return }.call
+ @reached_end_of_method = true
+ end
+ test
+ @reached_end_of_method.should be_true
+ end
+
+ it "allows long returns to flow through it" do
+ KernelSpecs::Lambda.new.outer.should == :good
+ end
+end
+
diff --git a/spec/rubyspec/core/kernel/load_spec.rb b/spec/rubyspec/core/kernel/load_spec.rb
new file mode 100644
index 0000000000..36cc07e38a
--- /dev/null
+++ b/spec/rubyspec/core/kernel/load_spec.rb
@@ -0,0 +1,40 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../../../fixtures/code_loading', __FILE__)
+require File.expand_path('../shared/load', __FILE__)
+require File.expand_path('../shared/require', __FILE__)
+
+describe "Kernel#load" do
+ before :each do
+ CodeLoadingSpecs.spec_setup
+ end
+
+ after :each do
+ CodeLoadingSpecs.spec_cleanup
+ end
+
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:load)
+ end
+
+ it_behaves_like :kernel_require_basic, :load, CodeLoadingSpecs::Method.new
+end
+
+describe "Kernel#load" do
+ it_behaves_like :kernel_load, :load, CodeLoadingSpecs::Method.new
+end
+
+describe "Kernel.load" do
+ before :each do
+ CodeLoadingSpecs.spec_setup
+ end
+
+ after :each do
+ CodeLoadingSpecs.spec_cleanup
+ end
+
+ it_behaves_like :kernel_require_basic, :load, Kernel
+end
+
+describe "Kernel.load" do
+ it_behaves_like :kernel_load, :load, Kernel
+end
diff --git a/spec/rubyspec/core/kernel/local_variables_spec.rb b/spec/rubyspec/core/kernel/local_variables_spec.rb
new file mode 100644
index 0000000000..7e8b364b4f
--- /dev/null
+++ b/spec/rubyspec/core/kernel/local_variables_spec.rb
@@ -0,0 +1,37 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#local_variables" do
+ after :each do
+ ScratchPad.clear
+ end
+
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:local_variables)
+ end
+
+ it "contains locals as they are added" do
+ a = 1
+ b = 2
+ local_variables.should include(:a, :b)
+ local_variables.length.should == 2
+ end
+
+ it "is accessible from bindings" do
+ def local_var_foo
+ a = 1
+ b = 2
+ binding
+ end
+ foo_binding = local_var_foo()
+ res = eval("local_variables",foo_binding)
+ res.should include(:a, :b)
+ res.length.should == 2
+ end
+
+ it "is accessible in eval" do
+ eval "a=1; b=2; ScratchPad.record local_variables"
+ ScratchPad.recorded.should include(:a, :b)
+ ScratchPad.recorded.length.should == 2
+ end
+end
diff --git a/spec/rubyspec/core/kernel/loop_spec.rb b/spec/rubyspec/core/kernel/loop_spec.rb
new file mode 100644
index 0000000000..f23e3afb02
--- /dev/null
+++ b/spec/rubyspec/core/kernel/loop_spec.rb
@@ -0,0 +1,81 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel.loop" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:loop)
+ end
+
+ it "calls block until it is terminated by a break" do
+ i = 0
+ loop do
+ i += 1
+ break if i == 10
+ end
+
+ i.should == 10
+ end
+
+ it "returns value passed to break" do
+ loop do
+ break 123
+ end.should == 123
+ end
+
+ it "returns nil if no value passed to break" do
+ loop do
+ break
+ end.should == nil
+ end
+
+ it "returns an enumerator if no block given" do
+ enum = loop
+ enum.instance_of?(Enumerator).should be_true
+ cnt = 0
+ enum.each do |*args|
+ raise "Args should be empty #{args.inspect}" unless args.empty?
+ cnt += 1
+ break cnt if cnt >= 42
+ end.should == 42
+ end
+
+ it "rescues StopIteration" do
+ loop do
+ raise StopIteration
+ end
+ 42.should == 42
+ end
+
+ it "rescues StopIteration's subclasses" do
+ finish = Class.new StopIteration
+ loop do
+ raise finish
+ end
+ 42.should == 42
+ end
+
+ it "does not rescue other errors" do
+ lambda{ loop do raise StandardError end }.should raise_error( StandardError )
+ end
+
+ ruby_version_is "2.3" do
+ it "returns StopIteration#result, the result value of a finished iterator" do
+ e = Enumerator.new { |y|
+ y << 1
+ y << 2
+ :stopped
+ }
+ loop { e.next }.should == :stopped
+ end
+ end
+
+ describe "when no block is given" do
+ describe "returned Enumerator" do
+ describe "size" do
+ it "returns Float::INFINITY" do
+ loop.size.should == Float::INFINITY
+ end
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/match_spec.rb b/spec/rubyspec/core/kernel/match_spec.rb
new file mode 100644
index 0000000000..8a117ed497
--- /dev/null
+++ b/spec/rubyspec/core/kernel/match_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Kernel#=~" do
+ it "returns nil matching any object" do
+ o = Object.new
+
+ (o =~ /Object/).should be_nil
+ (o =~ 'Object').should be_nil
+ (o =~ Object).should be_nil
+ (o =~ Object.new).should be_nil
+ (o =~ nil).should be_nil
+ (o =~ true).should be_nil
+ end
+end
diff --git a/spec/rubyspec/core/kernel/method_spec.rb b/spec/rubyspec/core/kernel/method_spec.rb
new file mode 100644
index 0000000000..09a3f940ca
--- /dev/null
+++ b/spec/rubyspec/core/kernel/method_spec.rb
@@ -0,0 +1,37 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/method', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#method" do
+ it_behaves_like(:kernel_method, :method)
+
+ before :each do
+ @obj = KernelSpecs::A.new
+ end
+
+ it "can be called on a private method" do
+ @obj.send(:private_method).should == :private_method
+ @obj.method(:private_method).should be_an_instance_of(Method)
+ end
+
+ it "can be called on a protected method" do
+ @obj.send(:protected_method).should == :protected_method
+ @obj.method(:protected_method).should be_an_instance_of(Method)
+ end
+
+ it "will see an alias of the original method as == when in a derived class" do
+ obj = KernelSpecs::B.new
+ obj.method(:aliased_pub_method).should == obj.method(:pub_method)
+ end
+
+ it "can call methods created with define_method" do
+ m = @obj.method(:defined_method)
+ m.call.should == :defined
+ end
+
+ it "can be called even if we only repond_to_missing? method, true" do
+ m = KernelSpecs::RespondViaMissing.new.method(:handled_privately)
+ m.should be_an_instance_of(Method)
+ m.call(1, 2, 3).should == "Done handled_privately([1, 2, 3])"
+ end
+end
diff --git a/spec/rubyspec/core/kernel/methods_spec.rb b/spec/rubyspec/core/kernel/methods_spec.rb
new file mode 100644
index 0000000000..5dfb17d4cb
--- /dev/null
+++ b/spec/rubyspec/core/kernel/methods_spec.rb
@@ -0,0 +1,101 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../../../fixtures/reflection', __FILE__)
+
+# TODO: rewrite
+describe "Kernel#methods" do
+ it "returns singleton methods defined by obj.meth" do
+ KernelSpecs::Methods.methods(false).should include(:ichi)
+ end
+
+ it "returns singleton methods defined in 'class << self'" do
+ KernelSpecs::Methods.methods(false).should include(:san)
+ end
+
+ it "returns private singleton methods defined by obj.meth" do
+ KernelSpecs::Methods.methods(false).should include(:shi)
+ end
+
+ it "returns singleton methods defined in 'class << self' when it follows 'private'" do
+ KernelSpecs::Methods.methods(false).should include(:roku)
+ end
+
+ it "does not return private singleton methods defined in 'class << self'" do
+ KernelSpecs::Methods.methods(false).should_not include(:shichi)
+ end
+
+ it "returns the publicly accessible methods of the object" do
+ meths = KernelSpecs::Methods.methods(false)
+ meths.should include(:hachi, :ichi, :juu, :juu_ichi,
+ :juu_ni, :roku, :san, :shi)
+
+ KernelSpecs::Methods.new.methods(false).should == []
+ end
+
+ it "returns the publicly accessible methods in the object, its ancestors and mixed-in modules" do
+ meths = KernelSpecs::Methods.methods(false) & KernelSpecs::Methods.methods
+ meths.should include(:hachi, :ichi, :juu, :juu_ichi,
+ :juu_ni, :roku, :san, :shi)
+
+ KernelSpecs::Methods.new.methods.should include(:ku, :ni, :juu_san)
+ end
+
+ it "returns methods added to the metaclass through extend" do
+ meth = KernelSpecs::Methods.new
+ meth.methods.should_not include(:peekaboo)
+ meth.extend(KernelSpecs::Methods::MetaclassMethods)
+ meth.methods.should include(:peekaboo)
+ end
+
+ it "does not return undefined singleton methods defined by obj.meth" do
+ o = KernelSpecs::Child.new
+ def o.single; end
+ o.methods.should include(:single)
+
+ class << o; self; end.send :undef_method, :single
+ o.methods.should_not include(:single)
+ end
+
+ it "does not return superclass methods undefined in the object's class" do
+ KernelSpecs::Child.new.methods.should_not include(:parent_method)
+ end
+
+ it "does not return superclass methods undefined in a superclass" do
+ KernelSpecs::Grandchild.new.methods.should_not include(:parent_method)
+ end
+
+ it "does not return included module methods undefined in the object's class" do
+ KernelSpecs::Grandchild.new.methods.should_not include(:parent_mixin_method)
+ end
+end
+
+describe :kernel_methods_supers, shared: true do
+ before :all do
+ @ms = [:pro, :pub]
+ end
+
+ it "returns a unique list for an object extended by a module" do
+ m = ReflectSpecs.oed.methods(*@object)
+ m.select { |x| @ms.include? x }.sort.should == @ms
+ end
+
+ it "returns a unique list for a class including a module" do
+ m = ReflectSpecs::D.new.methods(*@object)
+ m.select { |x| @ms.include? x }.sort.should == @ms
+ end
+
+ it "returns a unique list for a subclass of a class that includes a module" do
+ m = ReflectSpecs::E.new.methods(*@object)
+ m.select { |x| @ms.include? x }.sort.should == @ms
+ end
+end
+
+describe "Kernel#methods" do
+ describe "when not passed an argument" do
+ it_behaves_like :kernel_methods_supers, nil, []
+ end
+
+ describe "when passed true" do
+ it_behaves_like :kernel_methods_supers, nil, true
+ end
+end
diff --git a/spec/rubyspec/core/kernel/nil_spec.rb b/spec/rubyspec/core/kernel/nil_spec.rb
new file mode 100644
index 0000000000..0b5e34f7f1
--- /dev/null
+++ b/spec/rubyspec/core/kernel/nil_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#nil?" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/not_match_spec.rb b/spec/rubyspec/core/kernel/not_match_spec.rb
new file mode 100644
index 0000000000..42bd45c106
--- /dev/null
+++ b/spec/rubyspec/core/kernel/not_match_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#!~" do
+ class KernelSpecs::NotMatch
+ def !~(obj)
+ :foo
+ end
+ end
+
+ it 'calls =~ internally and negates the result' do
+ obj = Object.new
+ obj.should_receive(:=~).and_return(true)
+ (obj !~ :foo).should == false
+ end
+
+ it 'can be overridden in subclasses' do
+ obj = KernelSpecs::NotMatch.new
+ (obj !~ :bar).should == :foo
+ end
+end
diff --git a/spec/rubyspec/core/kernel/object_id_spec.rb b/spec/rubyspec/core/kernel/object_id_spec.rb
new file mode 100644
index 0000000000..0a12415a40
--- /dev/null
+++ b/spec/rubyspec/core/kernel/object_id_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../../../shared/kernel/object_id', __FILE__)
+
+describe "Kernel#object_id" do
+ it_behaves_like :object_id, :object_id, Object
+end
diff --git a/spec/rubyspec/core/kernel/open_spec.rb b/spec/rubyspec/core/kernel/open_spec.rb
new file mode 100644
index 0000000000..4e99061219
--- /dev/null
+++ b/spec/rubyspec/core/kernel/open_spec.rb
@@ -0,0 +1,141 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#open" do
+
+ before :each do
+ @name = tmp("kernel_open.txt")
+ @content = "This is a test"
+ touch(@name) { |f| f.write @content }
+ @file = nil
+ end
+
+ after :each do
+ @file.close if @file
+ rm_r @name
+ end
+
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:open)
+ end
+
+ it "opens a file when given a valid filename" do
+ @file = open(@name)
+ @file.should be_kind_of(File)
+ end
+
+ it "opens a file when called with a block" do
+ open(@name, "r") { |f| f.gets }.should == @content
+ end
+
+ platform_is_not :windows do
+ it "opens an io when path starts with a pipe" do
+ @io = open("|date")
+ begin
+ @io.should be_kind_of(IO)
+ ensure
+ @io.close
+ end
+ end
+
+ it "opens an io when called with a block" do
+ @output = open("|date") { |f| f.gets }
+ @output.should_not == ''
+ end
+
+ it "opens an io for writing" do
+ bytes = open("|cat", "w") { |io| io.write(".") }
+ bytes.should == 1
+ end
+ end
+
+ platform_is :windows do
+ it "opens an io when path starts with a pipe" do
+ @io = open("|date /t")
+ begin
+ @io.should be_kind_of(IO)
+ @io.read
+ ensure
+ @io.close
+ end
+ end
+
+ it "opens an io when called with a block" do
+ @output = open("|date /t") { |f| f.gets }
+ @output.should_not == ''
+ end
+ end
+
+ it "raises an ArgumentError if not passed one argument" do
+ lambda { open }.should raise_error(ArgumentError)
+ end
+
+ describe "when given an object that responds to to_open" do
+ before :each do
+ ScratchPad.clear
+ end
+
+ it "calls #to_path to covert the argument to a String before calling #to_str" do
+ obj = mock("open to_path")
+ obj.should_receive(:to_path).at_least(1).times.and_return(@name)
+ obj.should_not_receive(:to_str)
+
+ open(obj, "r") { |f| f.gets }.should == @content
+ end
+
+ it "calls #to_str to convert the argument to a String" do
+ obj = mock("open to_str")
+ obj.should_receive(:to_str).at_least(1).times.and_return(@name)
+
+ open(obj, "r") { |f| f.gets }.should == @content
+ end
+
+ it "calls #to_open on argument" do
+ obj = mock('fileish')
+ @file = File.open(@name)
+ obj.should_receive(:to_open).and_return(@file)
+ @file = open(obj)
+ @file.should be_kind_of(File)
+ end
+
+ it "returns the value from #to_open" do
+ obj = mock('to_open')
+ obj.should_receive(:to_open).and_return(:value)
+
+ open(obj).should == :value
+ end
+
+ it "passes its arguments onto #to_open" do
+ obj = mock('to_open')
+ obj.should_receive(:to_open).with(1,2,3)
+
+ open(obj, 1, 2, 3)
+ end
+
+ it "passes the return value from #to_open to a block" do
+ obj = mock('to_open')
+ obj.should_receive(:to_open).and_return(:value)
+
+ open(obj) do |mock|
+ ScratchPad.record(mock)
+ end
+
+ ScratchPad.recorded.should == :value
+ end
+ end
+
+ it "raises a TypeError if passed a non-String that does not respond to #to_open" do
+ obj = mock('non-fileish')
+ lambda { open(obj) }.should raise_error(TypeError)
+ lambda { open(nil) }.should raise_error(TypeError)
+ lambda { open(7) }.should raise_error(TypeError)
+ end
+
+ it "accepts nil for mode and permission" do
+ open(@name, nil, nil) { |f| f.gets }.should == @content
+ end
+end
+
+describe "Kernel.open" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/p_spec.rb b/spec/rubyspec/core/kernel/p_spec.rb
new file mode 100644
index 0000000000..c451f5952a
--- /dev/null
+++ b/spec/rubyspec/core/kernel/p_spec.rb
@@ -0,0 +1,79 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#p" do
+ before :all do
+ @rs_f, @rs_b, @rs_c = $/, $\, $,
+ end
+
+ after :each do
+ $/, $\, $, = @rs_f, @rs_b, @rs_c
+ end
+
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:p)
+ end
+
+ # TODO: fix
+ it "flushes output if receiver is a File" do
+ filename = tmp("Kernel_p_flush") + $$.to_s
+ begin
+ File.open(filename, "w") do |f|
+ begin
+ old_stdout = $stdout
+ $stdout = f
+ p("abcde")
+ ensure
+ $stdout = old_stdout
+ end
+
+ File.open(filename) do |f2|
+ f2.read(7).should == "\"abcde\""
+ end
+ end
+ ensure
+ rm_r filename
+ end
+ end
+
+ it "prints obj.inspect followed by system record separator for each argument given" do
+ o = mock("Inspector Gadget")
+ o.should_receive(:inspect).any_number_of_times.and_return "Next time, Gadget, NEXT TIME!"
+
+ lambda { p(o) }.should output("Next time, Gadget, NEXT TIME!\n")
+ lambda { p(*[o]) }.should output("Next time, Gadget, NEXT TIME!\n")
+ lambda { p(*[o, o]) }.should output("Next time, Gadget, NEXT TIME!\nNext time, Gadget, NEXT TIME!\n")
+ lambda { p([o])}.should output("[#{o.inspect}]\n")
+ end
+
+ it "is not affected by setting $\\, $/ or $," do
+ o = mock("Inspector Gadget")
+ o.should_receive(:inspect).any_number_of_times.and_return "Next time, Gadget, NEXT TIME!"
+
+ $, = " *helicopter sound*\n"
+ lambda { p(o) }.should output_to_fd("Next time, Gadget, NEXT TIME!\n")
+
+ $\ = " *helicopter sound*\n"
+ lambda { p(o) }.should output_to_fd("Next time, Gadget, NEXT TIME!\n")
+
+ $/ = " *helicopter sound*\n"
+ lambda { p(o) }.should output_to_fd("Next time, Gadget, NEXT TIME!\n")
+ end
+
+ it "prints nothing if no argument is given" do
+ lambda { p }.should output("")
+ end
+
+ it "prints nothing if called splatting an empty Array" do
+ lambda { p(*[]) }.should output("")
+ end
+
+=begin Not sure how to spec this, but wanted to note the behavior here
+ it "does not flush if receiver is not a TTY or a File" do
+ end
+=end
+end
+
+describe "Kernel.p" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/print_spec.rb b/spec/rubyspec/core/kernel/print_spec.rb
new file mode 100644
index 0000000000..3b642538cb
--- /dev/null
+++ b/spec/rubyspec/core/kernel/print_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#print" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:print)
+ end
+end
+
+describe "Kernel.print" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/printf_spec.rb b/spec/rubyspec/core/kernel/printf_spec.rb
new file mode 100644
index 0000000000..b4c68fa449
--- /dev/null
+++ b/spec/rubyspec/core/kernel/printf_spec.rb
@@ -0,0 +1,34 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#printf" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:printf)
+ end
+end
+
+describe "Kernel.printf" do
+
+ before :each do
+ @stdout = $stdout
+ @name = tmp("kernel_puts.txt")
+ $stdout = new_io @name
+ end
+
+ after :each do
+ $stdout.close
+ $stdout = @stdout
+ rm_r @name
+ end
+
+ it "writes to stdout when a string is the first argument" do
+ $stdout.should_receive(:write).with("string")
+ Kernel.printf("%s", "string")
+ end
+
+ it "calls write on the first argument when it is not a string" do
+ object = mock('io')
+ object.should_receive(:write).with("string")
+ Kernel.printf(object, "%s", "string")
+ end
+end
diff --git a/spec/rubyspec/core/kernel/private_methods_spec.rb b/spec/rubyspec/core/kernel/private_methods_spec.rb
new file mode 100644
index 0000000000..d0603c72b8
--- /dev/null
+++ b/spec/rubyspec/core/kernel/private_methods_spec.rb
@@ -0,0 +1,69 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../../../fixtures/reflection', __FILE__)
+
+# TODO: rewrite
+describe "Kernel#private_methods" do
+ it "returns a list of the names of privately accessible methods in the object" do
+ m = KernelSpecs::Methods.private_methods(false)
+ m.should include(:shichi)
+ m = KernelSpecs::Methods.new.private_methods(false)
+ m.should include(:juu_shi)
+ end
+
+ it "returns a list of the names of privately accessible methods in the object and its ancestors and mixed-in modules" do
+ m = (KernelSpecs::Methods.private_methods(false) & KernelSpecs::Methods.private_methods)
+
+ m.should include(:shichi)
+ m = KernelSpecs::Methods.new.private_methods
+ m.should include(:juu_shi)
+ end
+
+ it "returns private methods mixed in to the metaclass" do
+ m = KernelSpecs::Methods.new
+ m.extend(KernelSpecs::Methods::MetaclassMethods)
+ m.private_methods.should include(:shoo)
+ end
+end
+
+describe :kernel_private_methods_supers, shared: true do
+ it "returns a unique list for an object extended by a module" do
+ m = ReflectSpecs.oed.private_methods(*@object)
+ m.select { |x| x == :pri }.sort.should == [:pri]
+ end
+
+ it "returns a unique list for a class including a module" do
+ m = ReflectSpecs::D.new.private_methods(*@object)
+ m.select { |x| x == :pri }.sort.should == [:pri]
+ end
+
+ it "returns a unique list for a subclass of a class that includes a module" do
+ m = ReflectSpecs::E.new.private_methods(*@object)
+ m.select { |x| x == :pri }.sort.should == [:pri]
+ end
+end
+
+describe :kernel_private_methods_with_falsy, shared: true do
+ it "returns a list of private methods in without its ancestors" do
+ ReflectSpecs::F.private_methods(@object).select{|m|/_pri\z/ =~ m}.sort.should == [:ds_pri, :fs_pri]
+ ReflectSpecs::F.new.private_methods(@object).should == [:f_pri]
+ end
+end
+
+describe "Kernel#private_methods" do
+ describe "when not passed an argument" do
+ it_behaves_like :kernel_private_methods_supers, nil, []
+ end
+
+ describe "when passed true" do
+ it_behaves_like :kernel_private_methods_supers, nil, true
+ end
+
+ describe "when passed false" do
+ it_behaves_like :kernel_private_methods_with_falsy, nil, false
+ end
+
+ describe "when passed nil" do
+ it_behaves_like :kernel_private_methods_with_falsy, nil, nil
+ end
+end
diff --git a/spec/rubyspec/core/kernel/proc_spec.rb b/spec/rubyspec/core/kernel/proc_spec.rb
new file mode 100644
index 0000000000..4e4854f97d
--- /dev/null
+++ b/spec/rubyspec/core/kernel/proc_spec.rb
@@ -0,0 +1,50 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/lambda', __FILE__)
+
+# The functionality of Proc objects is specified in core/proc
+
+describe "Kernel.proc" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:proc)
+ end
+
+ it "creates a proc-style Proc if given a literal block" do
+ l = proc { 42 }
+ l.lambda?.should be_false
+ end
+
+ it "returned the passed Proc if given an existing Proc" do
+ some_lambda = lambda {}
+ some_lambda.lambda?.should be_true
+ l = proc(&some_lambda)
+ l.should equal(some_lambda)
+ l.lambda?.should be_true
+ end
+
+ it_behaves_like(:kernel_lambda, :proc)
+
+ it "returns from the creation site of the proc, not just the proc itself" do
+ @reached_end_of_method = nil
+ def test
+ proc { return }.call
+ @reached_end_of_method = true
+ end
+ test
+ @reached_end_of_method.should be_nil
+ end
+end
+
+describe "Kernel#proc" do
+ it "uses the implicit block from an enclosing method" do
+ def some_method
+ proc
+ end
+
+ prc = some_method { "hello" }
+
+ prc.call.should == "hello"
+ end
+
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/protected_methods_spec.rb b/spec/rubyspec/core/kernel/protected_methods_spec.rb
new file mode 100644
index 0000000000..2e09cead53
--- /dev/null
+++ b/spec/rubyspec/core/kernel/protected_methods_spec.rb
@@ -0,0 +1,69 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../../../fixtures/reflection', __FILE__)
+
+# TODO: rewrite
+
+# The reason why having include() is to show the specification explicitly.
+# You should use have_protected_method() with the exception of this spec.
+describe "Kernel#protected_methods" do
+ it "returns a list of the names of protected methods accessible in the object" do
+ KernelSpecs::Methods.protected_methods(false).sort.should include(:juu_ichi)
+ KernelSpecs::Methods.new.protected_methods(false).should include(:ku)
+ end
+
+ it "returns a list of the names of protected methods accessible in the object and from its ancestors and mixed-in modules" do
+ l1 = KernelSpecs::Methods.protected_methods(false)
+ l2 = KernelSpecs::Methods.protected_methods
+ (l1 & l2).should include(:juu_ichi)
+ KernelSpecs::Methods.new.protected_methods.should include(:ku)
+ end
+
+ it "returns methods mixed in to the metaclass" do
+ m = KernelSpecs::Methods.new
+ m.extend(KernelSpecs::Methods::MetaclassMethods)
+ m.protected_methods.should include(:nopeeking)
+ end
+end
+
+describe :kernel_protected_methods_supers, shared: true do
+ it "returns a unique list for an object extended by a module" do
+ m = ReflectSpecs.oed.protected_methods(*@object)
+ m.select { |x| x == :pro }.sort.should == [:pro]
+ end
+
+ it "returns a unique list for a class including a module" do
+ m = ReflectSpecs::D.new.protected_methods(*@object)
+ m.select { |x| x == :pro }.sort.should == [:pro]
+ end
+
+ it "returns a unique list for a subclass of a class that includes a module" do
+ m = ReflectSpecs::E.new.protected_methods(*@object)
+ m.select { |x| x == :pro }.sort.should == [:pro]
+ end
+end
+
+describe :kernel_protected_methods_with_falsy, shared: true do
+ it "returns a list of protected methods in without its ancestors" do
+ ReflectSpecs::F.protected_methods(@object).select{|m|/_pro\z/ =~ m}.sort.should == [:ds_pro, :fs_pro]
+ ReflectSpecs::F.new.protected_methods(@object).should == [:f_pro]
+ end
+end
+
+describe "Kernel#protected_methods" do
+ describe "when not passed an argument" do
+ it_behaves_like :kernel_protected_methods_supers, nil, []
+ end
+
+ describe "when passed true" do
+ it_behaves_like :kernel_protected_methods_supers, nil, true
+ end
+
+ describe "when passed false" do
+ it_behaves_like :kernel_protected_methods_with_falsy, nil, false
+ end
+
+ describe "when passed nil" do
+ it_behaves_like :kernel_protected_methods_with_falsy, nil, nil
+ end
+end
diff --git a/spec/rubyspec/core/kernel/public_method_spec.rb b/spec/rubyspec/core/kernel/public_method_spec.rb
new file mode 100644
index 0000000000..c4a29d9192
--- /dev/null
+++ b/spec/rubyspec/core/kernel/public_method_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/method', __FILE__)
+
+describe "Kernel#public_method" do
+ it_behaves_like(:kernel_method, :public_method)
+
+ before :each do
+ @obj = KernelSpecs::A.new
+ end
+
+ it "raises a NameError when called on a private method" do
+ @obj.send(:private_method).should == :private_method
+ lambda do
+ @obj.public_method(:private_method)
+ end.should raise_error(NameError)
+ end
+
+ it "raises a NameError when called on a protected method" do
+ @obj.send(:protected_method).should == :protected_method
+ lambda do
+ @obj.public_method(:protected_method)
+ end.should raise_error(NameError)
+ end
+
+ it "raises a NameError if we only repond_to_missing? method, true" do
+ obj = KernelSpecs::RespondViaMissing.new
+ lambda do
+ obj.public_method(:handled_privately)
+ end.should raise_error(NameError)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/public_methods_spec.rb b/spec/rubyspec/core/kernel/public_methods_spec.rb
new file mode 100644
index 0000000000..b72775483c
--- /dev/null
+++ b/spec/rubyspec/core/kernel/public_methods_spec.rb
@@ -0,0 +1,76 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../../../fixtures/reflection', __FILE__)
+
+# TODO: rewrite
+describe "Kernel#public_methods" do
+ it "returns a list of the names of publicly accessible methods in the object" do
+ KernelSpecs::Methods.public_methods(false).sort.should include(:hachi,
+ :ichi, :juu, :juu_ni, :roku, :san, :shi)
+ KernelSpecs::Methods.new.public_methods(false).sort.should include(:juu_san, :ni)
+ end
+
+ it "returns a list of names without protected accessible methods in the object" do
+ KernelSpecs::Methods.public_methods(false).sort.should_not include(:juu_ichi)
+ KernelSpecs::Methods.new.public_methods(false).sort.should_not include(:ku)
+ end
+
+ it "returns a list of the names of publicly accessible methods in the object and its ancestors and mixed-in modules" do
+ (KernelSpecs::Methods.public_methods(false) & KernelSpecs::Methods.public_methods).sort.should include(
+ :hachi, :ichi, :juu, :juu_ni, :roku, :san, :shi)
+ m = KernelSpecs::Methods.new.public_methods
+ m.should include(:ni, :juu_san)
+ end
+
+ it "returns methods mixed in to the metaclass" do
+ m = KernelSpecs::Methods.new
+ m.extend(KernelSpecs::Methods::MetaclassMethods)
+ m.public_methods.should include(:peekaboo)
+ end
+
+ it "returns public methods for immediates" do
+ 10.public_methods.should include(:divmod)
+ end
+end
+
+describe :kernel_public_methods_supers, shared: true do
+ it "returns a unique list for an object extended by a module" do
+ m = ReflectSpecs.oed.public_methods(*@object)
+ m.select { |x| x == :pub }.sort.should == [:pub]
+ end
+
+ it "returns a unique list for a class including a module" do
+ m = ReflectSpecs::D.new.public_methods(*@object)
+ m.select { |x| x == :pub }.sort.should == [:pub]
+ end
+
+ it "returns a unique list for a subclass of a class that includes a module" do
+ m = ReflectSpecs::E.new.public_methods(*@object)
+ m.select { |x| x == :pub }.sort.should == [:pub]
+ end
+end
+
+describe :kernel_public_methods_with_falsy, shared: true do
+ it "returns a list of public methods in without its ancestors" do
+ ReflectSpecs::F.public_methods(@object).select{|m|/_pub\z/ =~ m}.sort.should == [:ds_pub, :fs_pub]
+ ReflectSpecs::F.new.public_methods(@object).should == [:f_pub]
+ end
+end
+
+describe "Kernel#public_methods" do
+ describe "when not passed an argument" do
+ it_behaves_like :kernel_public_methods_supers, nil, []
+ end
+
+ describe "when passed true" do
+ it_behaves_like :kernel_public_methods_supers, nil, true
+ end
+
+ describe "when passed false" do
+ it_behaves_like :kernel_public_methods_with_falsy, nil, false
+ end
+
+ describe "when passed nil" do
+ it_behaves_like :kernel_public_methods_with_falsy, nil, nil
+ end
+end
diff --git a/spec/rubyspec/core/kernel/public_send_spec.rb b/spec/rubyspec/core/kernel/public_send_spec.rb
new file mode 100644
index 0000000000..2eabbc7dc9
--- /dev/null
+++ b/spec/rubyspec/core/kernel/public_send_spec.rb
@@ -0,0 +1,108 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../../../shared/basicobject/send', __FILE__)
+
+describe "Kernel#public_send" do
+ it "invokes the named public method" do
+ class KernelSpecs::Foo
+ def bar
+ 'done'
+ end
+ end
+ KernelSpecs::Foo.new.public_send(:bar).should == 'done'
+ end
+
+ it "invokes the named alias of a public method" do
+ class KernelSpecs::Foo
+ def bar
+ 'done'
+ end
+ alias :aka :bar
+ end
+ KernelSpecs::Foo.new.public_send(:aka).should == 'done'
+ end
+
+ it "raises a NoMethodError if the method is protected" do
+ class KernelSpecs::Foo
+ protected
+ def bar
+ 'done'
+ end
+ end
+ lambda { KernelSpecs::Foo.new.public_send(:bar)}.should raise_error(NoMethodError)
+ end
+
+ it "raises a NoMethodError if the named method is private" do
+ class KernelSpecs::Foo
+ private
+ def bar
+ 'done2'
+ end
+ end
+ lambda {
+ KernelSpecs::Foo.new.public_send(:bar)
+ }.should raise_error(NoMethodError)
+ end
+
+ context 'called from own public method' do
+ before do
+ class << @receiver = Object.new
+ def call_protected_method
+ public_send :protected_method
+ end
+
+ def call_private_method
+ public_send :private_method
+ end
+
+ protected
+
+ def protected_method
+ raise 'Should not called'
+ end
+
+ private
+
+ def private_method
+ raise 'Should not called'
+ end
+ end
+ end
+
+ it "raises a NoMethodError if the method is protected" do
+ lambda { @receiver.call_protected_method }.should raise_error(NoMethodError)
+ end
+
+ it "raises a NoMethodError if the method is private" do
+ lambda { @receiver.call_private_method }.should raise_error(NoMethodError)
+ end
+ end
+
+ it "raises a NoMethodError if the named method is an alias of a private method" do
+ class KernelSpecs::Foo
+ private
+ def bar
+ 'done2'
+ end
+ alias :aka :bar
+ end
+ lambda {
+ KernelSpecs::Foo.new.public_send(:aka)
+ }.should raise_error(NoMethodError)
+ end
+
+ it "raises a NoMethodError if the named method is an alias of a protected method" do
+ class KernelSpecs::Foo
+ protected
+ def bar
+ 'done2'
+ end
+ alias :aka :bar
+ end
+ lambda {
+ KernelSpecs::Foo.new.public_send(:aka)
+ }.should raise_error(NoMethodError)
+ end
+
+ it_behaves_like(:basicobject_send, :public_send)
+end
diff --git a/spec/rubyspec/core/kernel/putc_spec.rb b/spec/rubyspec/core/kernel/putc_spec.rb
new file mode 100644
index 0000000000..1f5e9b6d63
--- /dev/null
+++ b/spec/rubyspec/core/kernel/putc_spec.rb
@@ -0,0 +1,39 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../../../shared/io/putc', __FILE__)
+
+describe "Kernel#putc" do
+ it "is a private instance method" do
+ Kernel.should have_private_instance_method(:putc)
+ end
+end
+
+describe "Kernel.putc" do
+ before :each do
+ @name = tmp("kernel_putc.txt")
+ @io = new_io @name
+ @io_object = @object
+ @stdout, $stdout = $stdout, @io
+ end
+
+ after :each do
+ $stdout = @stdout
+ end
+
+ it_behaves_like :io_putc, :putc_method, KernelSpecs
+end
+
+describe "Kernel#putc" do
+ before :each do
+ @name = tmp("kernel_putc.txt")
+ @io = new_io @name
+ @io_object = @object
+ @stdout, $stdout = $stdout, @io
+ end
+
+ after :each do
+ $stdout = @stdout
+ end
+
+ it_behaves_like :io_putc, :putc_function, KernelSpecs
+end
diff --git a/spec/rubyspec/core/kernel/puts_spec.rb b/spec/rubyspec/core/kernel/puts_spec.rb
new file mode 100644
index 0000000000..c5297f1cb2
--- /dev/null
+++ b/spec/rubyspec/core/kernel/puts_spec.rb
@@ -0,0 +1,29 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#puts" do
+ before :each do
+ @stdout = $stdout
+ @name = tmp("kernel_puts.txt")
+ $stdout = new_io @name
+ end
+
+ after :each do
+ $stdout.close
+ $stdout = @stdout
+ rm_r @name
+ end
+
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:puts)
+ end
+
+ it "delegates to $stdout.puts" do
+ $stdout.should_receive(:puts).with(:arg)
+ puts :arg
+ end
+end
+
+describe "Kernel.puts" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/raise_spec.rb b/spec/rubyspec/core/kernel/raise_spec.rb
new file mode 100644
index 0000000000..6efffd9366
--- /dev/null
+++ b/spec/rubyspec/core/kernel/raise_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../../../shared/kernel/raise', __FILE__)
+
+describe "Kernel#raise" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:raise)
+ end
+end
+
+describe "Kernel#raise" do
+ it_behaves_like :kernel_raise, :raise, Kernel
+end
+
+describe "Kernel.raise" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/rand_spec.rb b/spec/rubyspec/core/kernel/rand_spec.rb
new file mode 100644
index 0000000000..f52b5f75b5
--- /dev/null
+++ b/spec/rubyspec/core/kernel/rand_spec.rb
@@ -0,0 +1,139 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel.rand" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:rand)
+ end
+
+ it "returns a float if no argument is passed" do
+ rand.should be_kind_of(Float)
+ end
+
+ it "returns an integer for an integer argument" do
+ rand(77).should be_kind_of(Integer)
+ end
+
+ it "returns an integer for a float argument greater than 1" do
+ rand(1.3).should be_kind_of(Integer)
+ end
+
+ it "returns a float for an argument between -1 and 1" do
+ rand(-0.999).should be_kind_of(Float)
+ rand(-0.01).should be_kind_of(Float)
+ rand(0).should be_kind_of(Float)
+ rand(0.01).should be_kind_of(Float)
+ rand(0.999).should be_kind_of(Float)
+ end
+
+ it "ignores the sign of the argument" do
+ [0, 1, 2, 3].should include(rand(-4))
+ end
+
+ it "never returns a value greater or equal to 1.0 with no arguments" do
+ 1000.times do
+ (0...1.0).should include(rand)
+ end
+ end
+
+ it "never returns a value greater or equal to any passed in max argument" do
+ 1000.times do
+ (0...100).to_a.should include(rand(100))
+ end
+ end
+
+ it "calls to_int on its argument" do
+ l = mock('limit')
+ l.should_receive(:to_int).and_return 7
+
+ rand l
+ end
+
+ context "given an exclusive range" do
+ it "returns an Integer between the two Integers" do
+ 1000.times do
+ x = rand(4...6)
+ x.should be_kind_of(Integer)
+ (4...6).should include(x)
+ end
+ end
+
+ it "returns a Float between the given Integer and Float" do
+ 1000.times do
+ x = rand(4...6.5)
+ x.should be_kind_of(Float)
+ (4...6.5).should include(x)
+ end
+ end
+
+ it "returns a Float between the given Float and Integer" do
+ 1000.times do
+ x = rand(3.5...6)
+ x.should be_kind_of(Float)
+ (3.5...6).should include(x)
+ end
+ end
+
+ it "returns a Float between the two given Floats" do
+ 1000.times do
+ x = rand(3.5...6.5)
+ x.should be_kind_of(Float)
+ (3.5...6.5).should include(x)
+ end
+ end
+ end
+
+ context "given an inclusive range" do
+ it "returns an Integer between the two Integers" do
+ 1000.times do
+ x = rand(4..6)
+ x.should be_kind_of(Integer)
+ (4..6).should include(x)
+ end
+ end
+
+ it "returns a Float between the given Integer and Float" do
+ 1000.times do
+ x = rand(4..6.5)
+ x.should be_kind_of(Float)
+ (4..6.5).should include(x)
+ end
+ end
+
+ it "returns a Float between the given Float and Integer" do
+ 1000.times do
+ x = rand(3.5..6)
+ x.should be_kind_of(Float)
+ (3.5..6).should include(x)
+ end
+ end
+
+ it "returns a Float between the two given Floats" do
+ 1000.times do
+ x = rand(3.5..6.5)
+ x.should be_kind_of(Float)
+ (3.5..6.5).should include(x)
+ end
+ end
+ end
+
+ it "returns a numeric for an range argument where max is < 1" do
+ rand(0.25..0.75).should be_kind_of(Numeric)
+ end
+
+ it "returns nil when range is backwards" do
+ rand(1..0).should be_nil
+ end
+
+ it "returns the range start/end when Float range is 0" do
+ rand(1.0..1.0).should eql(1.0)
+ end
+
+ it "returns the range start/end when Integer range is 0" do
+ rand(42..42).should eql(42)
+ end
+end
+
+describe "Kernel#rand" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/readline_spec.rb b/spec/rubyspec/core/kernel/readline_spec.rb
new file mode 100644
index 0000000000..c69eee0726
--- /dev/null
+++ b/spec/rubyspec/core/kernel/readline_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#readline" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:readline)
+ end
+end
+
+describe "Kernel.readline" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/readlines_spec.rb b/spec/rubyspec/core/kernel/readlines_spec.rb
new file mode 100644
index 0000000000..d5e07f8f75
--- /dev/null
+++ b/spec/rubyspec/core/kernel/readlines_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#readlines" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:readlines)
+ end
+end
+
+describe "Kernel.readlines" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/remove_instance_variable_spec.rb b/spec/rubyspec/core/kernel/remove_instance_variable_spec.rb
new file mode 100644
index 0000000000..6a9f78b9bc
--- /dev/null
+++ b/spec/rubyspec/core/kernel/remove_instance_variable_spec.rb
@@ -0,0 +1,59 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe :kernel_remove_instance_variable, shared: true do
+ it "returns the instance variable's value" do
+ value = @instance.send :remove_instance_variable, @object
+ value.should == "hello"
+ end
+
+ it "removes the instance variable" do
+ @instance.send :remove_instance_variable, @object
+ @instance.instance_variable_defined?(@object).should be_false
+ end
+end
+
+describe "Kernel#remove_instance_variable" do
+ before do
+ @instance = KernelSpecs::InstanceVariable.new
+ end
+
+ it "is a public method" do
+ Kernel.should have_public_instance_method(:remove_instance_variable, false)
+ end
+
+ it "raises a NameError if the instance variable is not defined" do
+ lambda do
+ @instance.send :remove_instance_variable, :@unknown
+ end.should raise_error(NameError)
+ end
+
+ it "raises a NameError if the argument is not a valid instance variable name" do
+ lambda do
+ @instance.send :remove_instance_variable, :"@0"
+ end.should raise_error(NameError)
+ end
+
+ it "raises a TypeError if passed an Object not defining #to_str" do
+ lambda do
+ obj = mock("kernel remove_instance_variable")
+ @instance.send :remove_instance_variable, obj
+ end.should raise_error(TypeError)
+ end
+
+ describe "when passed a String" do
+ it_behaves_like :kernel_remove_instance_variable, nil, "@greeting"
+ end
+
+ describe "when passed a Symbol" do
+ it_behaves_like :kernel_remove_instance_variable, nil, :@greeting
+ end
+
+ describe "when passed an Object" do
+ it "calls #to_str to convert the argument" do
+ name = mock("kernel remove_instance_variable")
+ name.should_receive(:to_str).and_return("@greeting")
+ @instance.send :remove_instance_variable, name
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/require_relative_spec.rb b/spec/rubyspec/core/kernel/require_relative_spec.rb
new file mode 100644
index 0000000000..04cf5444d2
--- /dev/null
+++ b/spec/rubyspec/core/kernel/require_relative_spec.rb
@@ -0,0 +1,349 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../../../fixtures/code_loading', __FILE__)
+
+describe "Kernel#require_relative with a relative path" do
+ it "needs to be reviewed for spec completeness"
+
+ before :each do
+ CodeLoadingSpecs.spec_setup
+ @dir = "../../fixtures/code"
+ @abs_dir = File.realpath(@dir, File.dirname(__FILE__))
+ @path = "#{@dir}/load_fixture.rb"
+ @abs_path = File.realpath(@path, File.dirname(__FILE__))
+ end
+
+ after :each do
+ CodeLoadingSpecs.spec_cleanup
+ end
+
+ platform_is_not :windows do
+ describe "when file is a symlink" do
+ before :each do
+ @link = tmp("symlink.rb", false)
+ @real_path = "#{@abs_dir}/symlink/symlink1.rb"
+ File.symlink(@real_path, @link)
+ end
+
+ after :each do
+ rm_r @link
+ end
+
+ it "loads a path relative to current file" do
+ require_relative(@link).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+ end
+ end
+
+ it "loads a path relative to the current file" do
+ require_relative(@path).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "loads a file defining many methods" do
+ require_relative("#{@dir}/methods_fixture.rb").should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "raises a LoadError if the file does not exist" do
+ lambda { require_relative("#{@dir}/nonexistent.rb") }.should raise_error(LoadError)
+ ScratchPad.recorded.should == []
+ end
+
+ it "raises a LoadError if basepath does not exist" do
+ lambda { eval("require_relative('#{@dir}/nonexistent.rb')") }.should raise_error(LoadError)
+ end
+
+ it "stores the missing path in a LoadError object" do
+ path = "#{@dir}/nonexistent.rb"
+
+ lambda {
+ require_relative(path)
+ }.should(raise_error(LoadError) { |e|
+ e.path.should == File.expand_path(path, @abs_dir)
+ })
+ end
+
+ it "calls #to_str on non-String objects" do
+ name = mock("load_fixture.rb mock")
+ name.should_receive(:to_str).and_return(@path)
+ require_relative(name).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "raises a TypeError if argument does not respond to #to_str" do
+ lambda { require_relative(nil) }.should raise_error(TypeError)
+ lambda { require_relative(42) }.should raise_error(TypeError)
+ lambda {
+ require_relative([@path,@path])
+ }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if passed an object that has #to_s but not #to_str" do
+ name = mock("load_fixture.rb mock")
+ name.stub!(:to_s).and_return(@path)
+ lambda { require_relative(name) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if #to_str does not return a String" do
+ name = mock("#to_str returns nil")
+ name.should_receive(:to_str).at_least(1).times.and_return(nil)
+ lambda { require_relative(name) }.should raise_error(TypeError)
+ end
+
+ it "calls #to_path on non-String objects" do
+ name = mock("load_fixture.rb mock")
+ name.should_receive(:to_path).and_return(@path)
+ require_relative(name).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "calls #to_str on non-String objects returned by #to_path" do
+ name = mock("load_fixture.rb mock")
+ to_path = mock("load_fixture_rb #to_path mock")
+ name.should_receive(:to_path).and_return(to_path)
+ to_path.should_receive(:to_str).and_return(@path)
+ require_relative(name).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ describe "(file extensions)" do
+ it "loads a .rb extensioned file when passed a non-extensioned path" do
+ require_relative("#{@dir}/load_fixture").should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "loads a .rb extensioned file when a C-extension file of the same name is loaded" do
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.bundle"
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.dylib"
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.so"
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.dll"
+ require_relative(@path).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "does not load a C-extension file if a .rb extensioned file is already loaded" do
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.rb"
+ require_relative("#{@dir}/load_fixture").should be_false
+ ScratchPad.recorded.should == []
+ end
+
+ it "loads a .rb extensioned file when passed a non-.rb extensioned path" do
+ require_relative("#{@dir}/load_fixture.ext").should be_true
+ ScratchPad.recorded.should == [:loaded]
+ $LOADED_FEATURES.should include "#{@abs_dir}/load_fixture.ext.rb"
+ end
+
+ it "loads a .rb extensioned file when a complex-extensioned C-extension file of the same name is loaded" do
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.ext.bundle"
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.ext.dylib"
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.ext.so"
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.ext.dll"
+ require_relative("#{@dir}/load_fixture.ext").should be_true
+ ScratchPad.recorded.should == [:loaded]
+ $LOADED_FEATURES.should include "#{@abs_dir}/load_fixture.ext.rb"
+ end
+
+ it "does not load a C-extension file if a complex-extensioned .rb file is already loaded" do
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.ext.rb"
+ require_relative("#{@dir}/load_fixture.ext").should be_false
+ ScratchPad.recorded.should == []
+ end
+ end
+
+ describe "($LOADED_FEATURES)" do
+ it "stores an absolute path" do
+ require_relative(@path).should be_true
+ $LOADED_FEATURES.should include(@abs_path)
+ end
+
+ it "does not store the path if the load fails" do
+ saved_loaded_features = $LOADED_FEATURES.dup
+ lambda { require_relative("#{@dir}/raise_fixture.rb") }.should raise_error(RuntimeError)
+ $LOADED_FEATURES.should == saved_loaded_features
+ end
+
+ it "does not load an absolute path that is already stored" do
+ $LOADED_FEATURES << @abs_path
+ require_relative(@path).should be_false
+ ScratchPad.recorded.should == []
+ end
+
+ it "adds the suffix of the resolved filename" do
+ require_relative("#{@dir}/load_fixture").should be_true
+ $LOADED_FEATURES.should include("#{@abs_dir}/load_fixture.rb")
+ end
+
+ it "loads a path for a file already loaded with a relative path" do
+ $LOAD_PATH << File.expand_path(@dir)
+ $LOADED_FEATURES << "load_fixture.rb" << "load_fixture"
+ require_relative(@path).should be_true
+ $LOADED_FEATURES.should include(@abs_path)
+ ScratchPad.recorded.should == [:loaded]
+ end
+ end
+end
+
+describe "Kernel#require_relative with an absolute path" do
+ it "needs to be reviewed for spec completeness"
+
+ before :each do
+ CodeLoadingSpecs.spec_setup
+ @dir = File.expand_path "../../fixtures/code", File.dirname(__FILE__)
+ @abs_dir = @dir
+ @path = File.join @dir, "load_fixture.rb"
+ @abs_path = @path
+ end
+
+ after :each do
+ CodeLoadingSpecs.spec_cleanup
+ end
+
+ it "loads a path relative to the current file" do
+ require_relative(@path).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "loads a file defining many methods" do
+ require_relative("#{@dir}/methods_fixture.rb").should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "raises a LoadError if the file does not exist" do
+ lambda { require_relative("#{@dir}/nonexistent.rb") }.should raise_error(LoadError)
+ ScratchPad.recorded.should == []
+ end
+
+ it "raises a LoadError if basepath does not exist" do
+ lambda { eval("require_relative('#{@dir}/nonexistent.rb')") }.should raise_error(LoadError)
+ end
+
+ it "stores the missing path in a LoadError object" do
+ path = "#{@dir}/nonexistent.rb"
+
+ lambda {
+ require_relative(path)
+ }.should(raise_error(LoadError) { |e|
+ e.path.should == File.expand_path(path, @abs_dir)
+ })
+ end
+
+ it "calls #to_str on non-String objects" do
+ name = mock("load_fixture.rb mock")
+ name.should_receive(:to_str).and_return(@path)
+ require_relative(name).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "raises a TypeError if argument does not respond to #to_str" do
+ lambda { require_relative(nil) }.should raise_error(TypeError)
+ lambda { require_relative(42) }.should raise_error(TypeError)
+ lambda {
+ require_relative([@path,@path])
+ }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if passed an object that has #to_s but not #to_str" do
+ name = mock("load_fixture.rb mock")
+ name.stub!(:to_s).and_return(@path)
+ lambda { require_relative(name) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if #to_str does not return a String" do
+ name = mock("#to_str returns nil")
+ name.should_receive(:to_str).at_least(1).times.and_return(nil)
+ lambda { require_relative(name) }.should raise_error(TypeError)
+ end
+
+ it "calls #to_path on non-String objects" do
+ name = mock("load_fixture.rb mock")
+ name.should_receive(:to_path).and_return(@path)
+ require_relative(name).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "calls #to_str on non-String objects returned by #to_path" do
+ name = mock("load_fixture.rb mock")
+ to_path = mock("load_fixture_rb #to_path mock")
+ name.should_receive(:to_path).and_return(to_path)
+ to_path.should_receive(:to_str).and_return(@path)
+ require_relative(name).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ describe "(file extensions)" do
+ it "loads a .rb extensioned file when passed a non-extensioned path" do
+ require_relative("#{@dir}/load_fixture").should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "loads a .rb extensioned file when a C-extension file of the same name is loaded" do
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.bundle"
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.dylib"
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.so"
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.dll"
+ require_relative(@path).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "does not load a C-extension file if a .rb extensioned file is already loaded" do
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.rb"
+ require_relative("#{@dir}/load_fixture").should be_false
+ ScratchPad.recorded.should == []
+ end
+
+ it "loads a .rb extensioned file when passed a non-.rb extensioned path" do
+ require_relative("#{@dir}/load_fixture.ext").should be_true
+ ScratchPad.recorded.should == [:loaded]
+ $LOADED_FEATURES.should include "#{@abs_dir}/load_fixture.ext.rb"
+ end
+
+ it "loads a .rb extensioned file when a complex-extensioned C-extension file of the same name is loaded" do
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.ext.bundle"
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.ext.dylib"
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.ext.so"
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.ext.dll"
+ require_relative("#{@dir}/load_fixture.ext").should be_true
+ ScratchPad.recorded.should == [:loaded]
+ $LOADED_FEATURES.should include "#{@abs_dir}/load_fixture.ext.rb"
+ end
+
+ it "does not load a C-extension file if a complex-extensioned .rb file is already loaded" do
+ $LOADED_FEATURES << "#{@abs_dir}/load_fixture.ext.rb"
+ require_relative("#{@dir}/load_fixture.ext").should be_false
+ ScratchPad.recorded.should == []
+ end
+ end
+
+ describe "($LOAD_FEATURES)" do
+ it "stores an absolute path" do
+ require_relative(@path).should be_true
+ $LOADED_FEATURES.should include(@abs_path)
+ end
+
+ it "does not store the path if the load fails" do
+ saved_loaded_features = $LOADED_FEATURES.dup
+ lambda { require_relative("#{@dir}/raise_fixture.rb") }.should raise_error(RuntimeError)
+ $LOADED_FEATURES.should == saved_loaded_features
+ end
+
+ it "does not load an absolute path that is already stored" do
+ $LOADED_FEATURES << @abs_path
+ require_relative(@path).should be_false
+ ScratchPad.recorded.should == []
+ end
+
+ it "adds the suffix of the resolved filename" do
+ require_relative("#{@dir}/load_fixture").should be_true
+ $LOADED_FEATURES.should include("#{@abs_dir}/load_fixture.rb")
+ end
+
+ it "loads a path for a file already loaded with a relative path" do
+ $LOAD_PATH << File.expand_path(@dir)
+ $LOADED_FEATURES << "load_fixture.rb" << "load_fixture"
+ require_relative(@path).should be_true
+ $LOADED_FEATURES.should include(@abs_path)
+ ScratchPad.recorded.should == [:loaded]
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/require_spec.rb b/spec/rubyspec/core/kernel/require_spec.rb
new file mode 100644
index 0000000000..75cea7565e
--- /dev/null
+++ b/spec/rubyspec/core/kernel/require_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../../../fixtures/code_loading', __FILE__)
+require File.expand_path('../shared/require', __FILE__)
+
+describe "Kernel#require" do
+ before :each do
+ CodeLoadingSpecs.spec_setup
+ end
+
+ after :each do
+ CodeLoadingSpecs.spec_cleanup
+ end
+
+ # if this fails, update your rubygems
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:require)
+ end
+
+ it_behaves_like :kernel_require_basic, :require, CodeLoadingSpecs::Method.new
+
+ it_behaves_like :kernel_require, :require, CodeLoadingSpecs::Method.new
+end
+
+describe "Kernel.require" do
+ before :each do
+ CodeLoadingSpecs.spec_setup
+ end
+
+ after :each do
+ CodeLoadingSpecs.spec_cleanup
+ end
+
+ it_behaves_like :kernel_require_basic, :require, Kernel
+
+ it_behaves_like :kernel_require, :require, Kernel
+end
diff --git a/spec/rubyspec/core/kernel/respond_to_missing_spec.rb b/spec/rubyspec/core/kernel/respond_to_missing_spec.rb
new file mode 100644
index 0000000000..f116f19dbd
--- /dev/null
+++ b/spec/rubyspec/core/kernel/respond_to_missing_spec.rb
@@ -0,0 +1,100 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#respond_to_missing?" do
+ before :each do
+ @a = KernelSpecs::A.new
+ end
+
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:respond_to_missing?, false)
+ end
+
+ it "is only an instance method" do
+ Kernel.method(:respond_to_missing?).owner.should == Kernel
+ end
+
+ it "is not called when #respond_to? would return true" do
+ obj = mock('object')
+ obj.stub!(:glark)
+ obj.should_not_receive(:respond_to_missing?)
+ obj.respond_to?(:glark).should be_true
+ end
+
+ it "is called with a 2nd argument of false when #respond_to? is" do
+ obj = mock('object')
+ obj.should_receive(:respond_to_missing?).with(:undefined_method, false)
+ obj.respond_to?(:undefined_method, false)
+ end
+
+ it "is called a 2nd argument of false when #respond_to? is called with only 1 argument" do
+ obj = mock('object')
+ obj.should_receive(:respond_to_missing?).with(:undefined_method, false)
+ obj.respond_to?(:undefined_method)
+ end
+
+ it "is called with true as the second argument when #respond_to? is" do
+ obj = mock('object')
+ obj.should_receive(:respond_to_missing?).with(:undefined_method, true)
+ obj.respond_to?(:undefined_method, true)
+ end
+
+ it "is called when #respond_to? would return false" do
+ obj = mock('object')
+ obj.should_receive(:respond_to_missing?).with(:undefined_method, false)
+ obj.respond_to?(:undefined_method)
+ end
+
+ it "causes #respond_to? to return true if called and not returning false" do
+ obj = mock('object')
+ obj.should_receive(:respond_to_missing?).with(:undefined_method, false).and_return(:glark)
+ obj.respond_to?(:undefined_method).should be_true
+ end
+
+ it "causes #respond_to? to return false if called and returning false" do
+ obj = mock('object')
+ obj.should_receive(:respond_to_missing?).with(:undefined_method, false).and_return(false)
+ obj.respond_to?(:undefined_method).should be_false
+ end
+
+ it "causes #respond_to? to return false if called and returning nil" do
+ obj = mock('object')
+ obj.should_receive(:respond_to_missing?).with(:undefined_method, false).and_return(nil)
+ obj.respond_to?(:undefined_method).should be_false
+ end
+
+ it "isn't called when obj responds to the given public method" do
+ @a.should_not_receive(:respond_to_missing?)
+ @a.respond_to?(:pub_method).should be_true
+ end
+
+ it "isn't called when obj responds to the given public method, include_private = true" do
+ @a.should_not_receive(:respond_to_missing?)
+ @a.respond_to?(:pub_method, true).should be_true
+ end
+
+ it "is called when obj responds to the given protected method, include_private = false" do
+ @a.should_receive(:respond_to_missing?)
+ @a.respond_to?(:protected_method, false).should be_false
+ end
+
+ it "isn't called when obj responds to the given protected method, include_private = true" do
+ @a.should_not_receive(:respond_to_missing?)
+ @a.respond_to?(:protected_method, true).should be_true
+ end
+
+ it "is called when obj responds to the given private method, include_private = false" do
+ @a.should_receive(:respond_to_missing?).with(:private_method, false)
+ @a.respond_to?(:private_method)
+ end
+
+ it "isn't called when obj responds to the given private method, include_private = true" do
+ @a.should_not_receive(:respond_to_missing?)
+ @a.respond_to?(:private_method, true).should be_true
+ end
+
+ it "is called for missing class methods" do
+ @a.class.should_receive(:respond_to_missing?).with(:oOoOoO, false)
+ @a.class.respond_to?(:oOoOoO)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/respond_to_spec.rb b/spec/rubyspec/core/kernel/respond_to_spec.rb
new file mode 100644
index 0000000000..aa4379277b
--- /dev/null
+++ b/spec/rubyspec/core/kernel/respond_to_spec.rb
@@ -0,0 +1,73 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#respond_to?" do
+ before :each do
+ @a = KernelSpecs::A.new
+ end
+
+ it "is a public method" do
+ Kernel.should have_public_instance_method(:respond_to?, false)
+ end
+
+ it "is only an instance method" do
+ Kernel.method(:respond_to?).owner.should == Kernel
+ end
+
+ it "returns false if the given method was undefined" do
+ @a.respond_to?(:undefed_method).should == false
+ @a.respond_to?("undefed_method").should == false
+ end
+
+ it "returns true if obj responds to the given public method" do
+ @a.respond_to?(:pub_method).should == true
+ @a.respond_to?("pub_method").should == true
+ end
+
+ it "throws a type error if argument can't be coerced into a Symbol" do
+ lambda { @a.respond_to?(Object.new) }.should raise_error(TypeError)
+ end
+
+ it "returns false if obj responds to the given protected method" do
+ @a.respond_to?(:protected_method).should == false
+ @a.respond_to?("protected_method").should == false
+ end
+
+ it "returns false if obj responds to the given private method" do
+ @a.respond_to?(:private_method).should == false
+ @a.respond_to?("private_method").should == false
+ end
+
+ it "returns true if obj responds to the given protected method (include_private = true)" do
+ @a.respond_to?(:protected_method, true).should == true
+ @a.respond_to?("protected_method", true).should == true
+ end
+
+ it "returns false if obj responds to the given protected method (include_private = false)" do
+ @a.respond_to?(:protected_method, false).should == false
+ @a.respond_to?("protected_method", false).should == false
+ end
+
+ it "returns false even if obj responds to the given private method (include_private = false)" do
+ @a.respond_to?(:private_method, false).should == false
+ @a.respond_to?("private_method", false).should == false
+ end
+
+ it "returns true if obj responds to the given private method (include_private = true)" do
+ @a.respond_to?(:private_method, true).should == true
+ @a.respond_to?("private_method", true).should == true
+ end
+
+ it "does not change method visibility when finding private method" do
+ KernelSpecs::VisibilityChange.respond_to?(:new, false).should == false
+ KernelSpecs::VisibilityChange.respond_to?(:new, true).should == true
+ lambda { KernelSpecs::VisibilityChange.new }.should raise_error(NoMethodError)
+ end
+
+ it "indicates if an object responds to a particular message" do
+ class KernelSpecs::Foo; def bar; 'done'; end; end
+ KernelSpecs::Foo.new.respond_to?(:bar).should == true
+ KernelSpecs::Foo.new.respond_to?(:invalid_and_silly_method_name).should == false
+ end
+
+end
diff --git a/spec/rubyspec/core/kernel/select_spec.rb b/spec/rubyspec/core/kernel/select_spec.rb
new file mode 100644
index 0000000000..c37c621ae7
--- /dev/null
+++ b/spec/rubyspec/core/kernel/select_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#select" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:select)
+ end
+end
+
+describe "Kernel.select" do
+ it "needs to be reviewed for spec completeness"
+
+ it 'does not block when timeout is 0' do
+ IO.pipe do |read, write|
+ IO.select([read], [], [], 0).should == nil
+ write.write 'data'
+ IO.select([read], [], [], 0).should == [[read], [], []]
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/send_spec.rb b/spec/rubyspec/core/kernel/send_spec.rb
new file mode 100644
index 0000000000..8afd16e97c
--- /dev/null
+++ b/spec/rubyspec/core/kernel/send_spec.rb
@@ -0,0 +1,68 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../../../shared/basicobject/send', __FILE__)
+
+describe "Kernel#send" do
+ it "invokes the named public method" do
+ class KernelSpecs::Foo
+ def bar
+ 'done'
+ end
+ end
+ KernelSpecs::Foo.new.send(:bar).should == 'done'
+ end
+
+ it "invokes the named alias of a public method" do
+ class KernelSpecs::Foo
+ def bar
+ 'done'
+ end
+ alias :aka :bar
+ end
+ KernelSpecs::Foo.new.send(:aka).should == 'done'
+ end
+
+ it "invokes the named protected method" do
+ class KernelSpecs::Foo
+ protected
+ def bar
+ 'done'
+ end
+ end
+ KernelSpecs::Foo.new.send(:bar).should == 'done'
+ end
+
+ it "invokes the named private method" do
+ class KernelSpecs::Foo
+ private
+ def bar
+ 'done2'
+ end
+ end
+ KernelSpecs::Foo.new.send(:bar).should == 'done2'
+ end
+
+ it "invokes the named alias of a private method" do
+ class KernelSpecs::Foo
+ private
+ def bar
+ 'done2'
+ end
+ alias :aka :bar
+ end
+ KernelSpecs::Foo.new.send(:aka).should == 'done2'
+ end
+
+ it "invokes the named alias of a protected method" do
+ class KernelSpecs::Foo
+ protected
+ def bar
+ 'done2'
+ end
+ alias :aka :bar
+ end
+ KernelSpecs::Foo.new.send(:aka).should == 'done2'
+ end
+
+ it_behaves_like(:basicobject_send, :send)
+end
diff --git a/spec/rubyspec/core/kernel/set_trace_func_spec.rb b/spec/rubyspec/core/kernel/set_trace_func_spec.rb
new file mode 100644
index 0000000000..5dafa8b5d3
--- /dev/null
+++ b/spec/rubyspec/core/kernel/set_trace_func_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#set_trace_func" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:set_trace_func)
+ end
+end
+
+describe "Kernel.set_trace_func" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/shared/dup_clone.rb b/spec/rubyspec/core/kernel/shared/dup_clone.rb
new file mode 100644
index 0000000000..320da8fc38
--- /dev/null
+++ b/spec/rubyspec/core/kernel/shared/dup_clone.rb
@@ -0,0 +1,125 @@
+class ObjectSpecDup
+ def initialize()
+ @obj = :original
+ end
+
+ attr_accessor :obj
+end
+
+class ObjectSpecDupInitCopy
+ def initialize()
+ @obj = :original
+ end
+
+ attr_accessor :obj, :original
+
+ def initialize_copy(original)
+ @obj = :init_copy
+ @original = original
+ end
+
+ private :initialize_copy
+end
+
+describe :kernel_dup_clone, shared: true do
+ it "returns a new object duplicated from the original" do
+ o = ObjectSpecDup.new
+ o2 = ObjectSpecDup.new
+
+ o.obj = 10
+
+ o3 = o.send(@method)
+
+ o3.obj.should == 10
+ o2.obj.should == :original
+ end
+
+ it "produces a shallow copy, contained objects are not recursively dupped" do
+ o = ObjectSpecDup.new
+ array = [1, 2]
+ o.obj = array
+
+ o2 = o.send(@method)
+ o2.obj.should equal(o.obj)
+ end
+
+ it "calls #initialize_copy on the NEW object if available, passing in original object" do
+ o = ObjectSpecDupInitCopy.new
+ o2 = o.send(@method)
+
+ o.obj.should == :original
+ o2.obj.should == :init_copy
+ o2.original.should equal(o)
+ end
+
+ it "preserves tainted state from the original" do
+ o = ObjectSpecDupInitCopy.new
+ o2 = o.send(@method)
+ o.taint
+ o3 = o.send(@method)
+
+ o2.tainted?.should == false
+ o3.tainted?.should == true
+ end
+
+ it "does not preserve the object_id" do
+ o1 = ObjectSpecDupInitCopy.new
+ old_object_id = o1.object_id
+ o2 = o1.send(@method)
+ o2.object_id.should_not == old_object_id
+ end
+
+ it "preserves untrusted state from the original" do
+ o = ObjectSpecDupInitCopy.new
+ o2 = o.send(@method)
+ o.untrust
+ o3 = o.send(@method)
+
+ o2.untrusted?.should == false
+ o3.untrusted?.should == true
+ end
+
+ ruby_version_is ''...'2.4' do
+ it "raises a TypeError for NilClass" do
+ lambda { nil.send(@method) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError for TrueClass" do
+ lambda { true.send(@method) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError for FalseClass" do
+ lambda { false.send(@method) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError for Fixnum" do
+ lambda { 1.send(@method) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError for Symbol" do
+ lambda { :my_symbol.send(@method) }.should raise_error(TypeError)
+ end
+ end
+
+ ruby_version_is '2.4' do
+ it "returns nil for NilClass" do
+ nil.send(@method).should == nil
+ end
+
+ it "returns true for TrueClass" do
+ true.send(@method).should == true
+ end
+
+ it "returns false for FalseClass" do
+ false.send(@method).should == false
+ end
+
+ it "returns the same Integer for Integer" do
+ 1.send(@method).should == 1
+ end
+
+ it "returns the same Symbol for Symbol" do
+ :my_symbol.send(@method).should == :my_symbol
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/shared/kind_of.rb b/spec/rubyspec/core/kernel/shared/kind_of.rb
new file mode 100644
index 0000000000..e99f46aa14
--- /dev/null
+++ b/spec/rubyspec/core/kernel/shared/kind_of.rb
@@ -0,0 +1,44 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :kernel_kind_of, shared: true do
+ before :each do
+ @o = KernelSpecs::KindaClass.new
+ end
+
+ it "returns true if given class is the object's class" do
+ @o.send(@method, KernelSpecs::KindaClass).should == true
+ end
+
+ it "returns true if given class is an ancestor of the object's class" do
+ @o.send(@method, KernelSpecs::AncestorClass).should == true
+ @o.send(@method, String).should == true
+ @o.send(@method, Object).should == true
+ end
+
+ it "returns false if the given class is not object's class nor an ancestor" do
+ @o.send(@method, Array).should == false
+ end
+
+ it "returns true if given a Module that is included in object's class" do
+ @o.send(@method, KernelSpecs::MyModule).should == true
+ end
+
+ it "returns true if given a Module that is included one of object's ancestors only" do
+ @o.send(@method, KernelSpecs::AncestorModule).should == true
+ end
+
+ it "returns true if given a Module that object has been extended with" do
+ @o.send(@method, KernelSpecs::MyExtensionModule).should == true
+ end
+
+ it "returns false if given a Module not included in object's class nor ancestors" do
+ @o.send(@method, KernelSpecs::SomeOtherModule).should == false
+ end
+
+ it "raises a TypeError if given an object that is not a Class nor a Module" do
+ lambda { @o.send(@method, 1) }.should raise_error(TypeError)
+ lambda { @o.send(@method, 'KindaClass') }.should raise_error(TypeError)
+ lambda { @o.send(@method, :KindaClass) }.should raise_error(TypeError)
+ lambda { @o.send(@method, Object.new) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/shared/lambda.rb b/spec/rubyspec/core/kernel/shared/lambda.rb
new file mode 100644
index 0000000000..bebb111c43
--- /dev/null
+++ b/spec/rubyspec/core/kernel/shared/lambda.rb
@@ -0,0 +1,9 @@
+describe :kernel_lambda, shared: true do
+ it "returns a Proc object" do
+ send(@method) { true }.kind_of?(Proc).should == true
+ end
+
+ it "raises an ArgumentError when no block is given" do
+ lambda { send(@method) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/shared/load.rb b/spec/rubyspec/core/kernel/shared/load.rb
new file mode 100644
index 0000000000..0ce7d58d2c
--- /dev/null
+++ b/spec/rubyspec/core/kernel/shared/load.rb
@@ -0,0 +1,139 @@
+describe :kernel_load, shared: true do
+ before :each do
+ CodeLoadingSpecs.spec_setup
+ @path = File.expand_path "load_fixture.rb", CODE_LOADING_DIR
+ end
+
+ after :each do
+ CodeLoadingSpecs.spec_cleanup
+ end
+
+ it "loads a non-extensioned file as a Ruby source file" do
+ path = File.expand_path "load_fixture", CODE_LOADING_DIR
+ @object.load(path).should be_true
+ ScratchPad.recorded.should == [:no_ext]
+ end
+
+ it "loads a non .rb extensioned file as a Ruby source file" do
+ path = File.expand_path "load_fixture.ext", CODE_LOADING_DIR
+ @object.load(path).should be_true
+ ScratchPad.recorded.should == [:no_rb_ext]
+ end
+
+ it "loads from the current working directory" do
+ Dir.chdir CODE_LOADING_DIR do
+ @object.load("load_fixture.rb").should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+ end
+
+ it "loads a file that recursively requires itself" do
+ path = File.expand_path "recursive_require_fixture.rb", CODE_LOADING_DIR
+ -> {
+ $VERBOSE = true
+ @object.load(path).should be_true
+ }.should complain(/circular require considered harmful/)
+ ScratchPad.recorded.should == [:loaded, :loaded]
+ end
+
+ it "loads a file that recursively loads itself" do
+ path = File.expand_path "recursive_load_fixture.rb", CODE_LOADING_DIR
+ @object.load(path).should be_true
+ ScratchPad.recorded.should == [:loaded, :loaded]
+ end
+
+ it "loads a file each time the method is called" do
+ @object.load(@path).should be_true
+ @object.load(@path).should be_true
+ ScratchPad.recorded.should == [:loaded, :loaded]
+ end
+
+ it "loads a file even when the name appears in $LOADED_FEATURES" do
+ $LOADED_FEATURES << @path
+ @object.load(@path).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "loads a file that has been loaded by #require" do
+ @object.require(@path).should be_true
+ @object.load(@path).should be_true
+ ScratchPad.recorded.should == [:loaded, :loaded]
+ end
+
+ it "loads file even after $LOAD_PATH change" do
+ $LOAD_PATH << CODE_LOADING_DIR
+ @object.load("load_fixture.rb").should be_true
+ $LOAD_PATH.unshift CODE_LOADING_DIR + "/gem"
+ @object.load("load_fixture.rb").should be_true
+ ScratchPad.recorded.should == [:loaded, :loaded_gem]
+ end
+
+ it "does not cause #require with the same path to fail" do
+ @object.load(@path).should be_true
+ @object.require(@path).should be_true
+ ScratchPad.recorded.should == [:loaded, :loaded]
+ end
+
+ it "does not add the loaded path to $LOADED_FEATURES" do
+ saved_loaded_features = $LOADED_FEATURES.dup
+ @object.load(@path).should be_true
+ $LOADED_FEATURES.should == saved_loaded_features
+ end
+
+ it "raises a LoadError if passed a non-extensioned path that does not exist but a .rb extensioned path does exist" do
+ path = File.expand_path "load_ext_fixture", CODE_LOADING_DIR
+ lambda { @object.load(path) }.should raise_error(LoadError)
+ end
+
+ describe "when passed true for 'wrap'" do
+ it "loads from an existing path" do
+ path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR
+ @object.load(path, true).should be_true
+ end
+
+ it "sets the enclosing scope to an anonymous module" do
+ path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR
+ @object.load(path, true)
+
+ Object.const_defined?(:LoadSpecWrap).should be_false
+ end
+
+ it "allows referencing outside namespaces" do
+ path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR
+ @object.load(path, true)
+
+ ScratchPad.recorded.first.should be_an_instance_of(Class)
+ end
+
+ describe "with top-level methods" do
+ before :each do
+ path = File.expand_path "load_wrap_method_fixture.rb", CODE_LOADING_DIR
+ @object.load(path, true)
+ end
+
+ it "allows calling top-level methods" do
+ ScratchPad.recorded.last.should == :load_wrap_loaded
+ end
+
+ it "does not pollute the receiver" do
+ lambda { @object.send(:top_level_method) }.should raise_error(NameError)
+ end
+ end
+ end
+
+ describe "(shell expansion)" do
+ before :each do
+ @env_home = ENV["HOME"]
+ ENV["HOME"] = CODE_LOADING_DIR
+ end
+
+ after :each do
+ ENV["HOME"] = @env_home
+ end
+
+ it "expands a tilde to the HOME environment variable as the path to load" do
+ @object.require("~/load_fixture.rb").should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/shared/method.rb b/spec/rubyspec/core/kernel/shared/method.rb
new file mode 100644
index 0000000000..1566c6ab09
--- /dev/null
+++ b/spec/rubyspec/core/kernel/shared/method.rb
@@ -0,0 +1,50 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe :kernel_method, shared: true do
+ it "returns a method object for a valid method" do
+ class KernelSpecs::Foo; def bar; 'done'; end; end
+ m = KernelSpecs::Foo.new.send(@method, :bar)
+ m.should be_an_instance_of Method
+ m.call.should == 'done'
+ end
+
+ it "returns a method object for a valid singleton method" do
+ class KernelSpecs::Foo; def self.bar; 'class done'; end; end
+ m = KernelSpecs::Foo.send(@method, :bar)
+ m.should be_an_instance_of Method
+ m.call.should == 'class done'
+ end
+
+ it "returns a method object if we repond_to_missing? method" do
+ m = KernelSpecs::RespondViaMissing.new.send(@method, :handled_publicly)
+ m.should be_an_instance_of Method
+ m.call(42).should == "Done handled_publicly([42])"
+ end
+
+ it "raises a NameError for an invalid method name" do
+ class KernelSpecs::Foo; def bar; 'done'; end; end
+ lambda {
+ KernelSpecs::Foo.new.send(@method, :invalid_and_silly_method_name)
+ }.should raise_error(NameError)
+ end
+
+ it "raises a NameError for an invalid singleton method name" do
+ class KernelSpecs::Foo; def self.bar; 'done'; end; end
+ lambda { KernelSpecs::Foo.send(@method, :baz) }.should raise_error(NameError)
+ end
+
+ it "changes the method called for super on a target aliased method" do
+ c1 = Class.new do
+ def a; 'a'; end
+ def b; 'b'; end
+ end
+ c2 = Class.new(c1) do
+ def a; super; end
+ alias b a
+ end
+
+ c2.new.a.should == 'a'
+ c2.new.b.should == 'a'
+ c2.new.send(@method, :b).call.should == 'a'
+ end
+end
diff --git a/spec/rubyspec/core/kernel/shared/require.rb b/spec/rubyspec/core/kernel/shared/require.rb
new file mode 100644
index 0000000000..3296c7f42a
--- /dev/null
+++ b/spec/rubyspec/core/kernel/shared/require.rb
@@ -0,0 +1,703 @@
+describe :kernel_require_basic, shared: true do
+ describe "(path resolution)" do
+ it "loads an absolute path" do
+ path = File.expand_path "load_fixture.rb", CODE_LOADING_DIR
+ @object.send(@method, path).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "loads a non-canonical absolute path" do
+ path = File.join CODE_LOADING_DIR, "..", "code", "load_fixture.rb"
+ @object.send(@method, path).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "loads a file defining many methods" do
+ path = File.expand_path "methods_fixture.rb", CODE_LOADING_DIR
+ @object.send(@method, path).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "raises a LoadError if the file does not exist" do
+ path = File.expand_path "nonexistent.rb", CODE_LOADING_DIR
+ File.exist?(path).should be_false
+ lambda { @object.send(@method, path) }.should raise_error(LoadError)
+ ScratchPad.recorded.should == []
+ end
+
+ # Can't make a file unreadable on these platforms
+ platform_is_not :windows, :cygwin do
+ describe "with an unreadable file" do
+ before :each do
+ @path = tmp("unreadable_file.rb")
+ touch @path
+ File.chmod 0000, @path
+ end
+
+ after :each do
+ File.chmod 0666, @path
+ rm_r @path
+ end
+
+ it "raises a LoadError" do
+ File.exist?(@path).should be_true
+ lambda { @object.send(@method, @path) }.should raise_error(LoadError)
+ end
+ end
+ end
+
+ it "calls #to_str on non-String objects" do
+ path = File.expand_path "load_fixture.rb", CODE_LOADING_DIR
+ name = mock("load_fixture.rb mock")
+ name.should_receive(:to_str).and_return(path)
+ @object.send(@method, name).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "raises a TypeError if passed nil" do
+ lambda { @object.send(@method, nil) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if passed a Fixnum" do
+ lambda { @object.send(@method, 42) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if passed an Array" do
+ lambda { @object.send(@method, []) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if passed an object that does not provide #to_str" do
+ lambda { @object.send(@method, mock("not a filename")) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if passed an object that has #to_s but not #to_str" do
+ name = mock("load_fixture.rb mock")
+ name.stub!(:to_s).and_return("load_fixture.rb")
+ $LOAD_PATH << "."
+ Dir.chdir CODE_LOADING_DIR do
+ lambda { @object.send(@method, name) }.should raise_error(TypeError)
+ end
+ end
+
+ it "raises a TypeError if #to_str does not return a String" do
+ name = mock("#to_str returns nil")
+ name.should_receive(:to_str).at_least(1).times.and_return(nil)
+ lambda { @object.send(@method, name) }.should raise_error(TypeError)
+ end
+
+ it "calls #to_path on non-String objects" do
+ name = mock("load_fixture.rb mock")
+ name.stub!(:to_path).and_return("load_fixture.rb")
+ $LOAD_PATH << "."
+ Dir.chdir CODE_LOADING_DIR do
+ @object.send(@method, name).should be_true
+ end
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "calls #to_path on a String" do
+ path = File.expand_path "load_fixture.rb", CODE_LOADING_DIR
+ str = mock("load_fixture.rb mock")
+ str.should_receive(:to_path).and_return(path)
+ @object.send(@method, str).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "calls #to_str on non-String objects returned by #to_path" do
+ path = File.expand_path "load_fixture.rb", CODE_LOADING_DIR
+ name = mock("load_fixture.rb mock")
+ to_path = mock("load_fixture_rb #to_path mock")
+ name.should_receive(:to_path).and_return(to_path)
+ to_path.should_receive(:to_str).and_return(path)
+ @object.send(@method, name).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ # "http://redmine.ruby-lang.org/issues/show/2578"
+ it "loads a ./ relative path from the current working directory with empty $LOAD_PATH" do
+ Dir.chdir CODE_LOADING_DIR do
+ @object.send(@method, "./load_fixture.rb").should be_true
+ end
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "loads a ../ relative path from the current working directory with empty $LOAD_PATH" do
+ Dir.chdir CODE_LOADING_DIR do
+ @object.send(@method, "../code/load_fixture.rb").should be_true
+ end
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "loads a ./ relative path from the current working directory with non-empty $LOAD_PATH" do
+ $LOAD_PATH << "an_irrelevant_dir"
+ Dir.chdir CODE_LOADING_DIR do
+ @object.send(@method, "./load_fixture.rb").should be_true
+ end
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "loads a ../ relative path from the current working directory with non-empty $LOAD_PATH" do
+ $LOAD_PATH << "an_irrelevant_dir"
+ Dir.chdir CODE_LOADING_DIR do
+ @object.send(@method, "../code/load_fixture.rb").should be_true
+ end
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "loads a non-canonical path from the current working directory with non-empty $LOAD_PATH" do
+ $LOAD_PATH << "an_irrelevant_dir"
+ Dir.chdir CODE_LOADING_DIR do
+ @object.send(@method, "../code/../code/load_fixture.rb").should be_true
+ end
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "resolves a filename against $LOAD_PATH entries" do
+ $LOAD_PATH << CODE_LOADING_DIR
+ @object.send(@method, "load_fixture.rb").should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "does not require file twice after $LOAD_PATH change" do
+ $LOAD_PATH << CODE_LOADING_DIR
+ @object.require("load_fixture.rb").should be_true
+ $LOAD_PATH.unshift CODE_LOADING_DIR + "/gem"
+ @object.require("load_fixture.rb").should be_false
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "does not resolve a ./ relative path against $LOAD_PATH entries" do
+ $LOAD_PATH << CODE_LOADING_DIR
+ lambda do
+ @object.send(@method, "./load_fixture.rb")
+ end.should raise_error(LoadError)
+ ScratchPad.recorded.should == []
+ end
+
+ it "does not resolve a ../ relative path against $LOAD_PATH entries" do
+ $LOAD_PATH << CODE_LOADING_DIR
+ lambda do
+ @object.send(@method, "../code/load_fixture.rb")
+ end.should raise_error(LoadError)
+ ScratchPad.recorded.should == []
+ end
+
+ it "resolves a non-canonical path against $LOAD_PATH entries" do
+ $LOAD_PATH << File.dirname(CODE_LOADING_DIR)
+ @object.send(@method, "code/../code/load_fixture.rb").should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "loads a path with duplicate path separators" do
+ $LOAD_PATH << "."
+ sep = File::Separator + File::Separator
+ path = ["..", "code", "load_fixture.rb"].join(sep)
+ Dir.chdir CODE_LOADING_DIR do
+ @object.send(@method, path).should be_true
+ end
+ ScratchPad.recorded.should == [:loaded]
+ end
+ end
+end
+
+describe :kernel_require, shared: true do
+ describe "(path resolution)" do
+ # For reference see [ruby-core:24155] in which matz confirms this feature is
+ # intentional for security reasons.
+ it "does not load a bare filename unless the current working directory is in $LOAD_PATH" do
+ Dir.chdir CODE_LOADING_DIR do
+ lambda { @object.require("load_fixture.rb") }.should raise_error(LoadError)
+ ScratchPad.recorded.should == []
+ end
+ end
+
+ it "does not load a relative path unless the current working directory is in $LOAD_PATH" do
+ Dir.chdir File.dirname(CODE_LOADING_DIR) do
+ lambda do
+ @object.require("code/load_fixture.rb")
+ end.should raise_error(LoadError)
+ ScratchPad.recorded.should == []
+ end
+ end
+
+ it "loads a file that recursively requires itself" do
+ path = File.expand_path "recursive_require_fixture.rb", CODE_LOADING_DIR
+ -> {
+ $VERBOSE = true
+ @object.require(path).should be_true
+ }.should complain(/circular require considered harmful/)
+ ScratchPad.recorded.should == [:loaded]
+ end
+ end
+
+ describe "(non-extensioned path)" do
+ before :each do
+ a = File.expand_path "a", CODE_LOADING_DIR
+ b = File.expand_path "b", CODE_LOADING_DIR
+ $LOAD_PATH.replace [a, b]
+ end
+
+ it "loads a .rb extensioned file when a C-extension file exists on an earlier load path" do
+ @object.require("load_fixture").should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+ end
+
+ describe "(file extensions)" do
+ it "loads a .rb extensioned file when passed a non-extensioned path" do
+ path = File.expand_path "load_fixture", CODE_LOADING_DIR
+ File.exist?(path).should be_true
+ @object.require(path).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "loads a .rb extensioned file when a C-extension file of the same name is loaded" do
+ $LOADED_FEATURES << File.expand_path("load_fixture.bundle", CODE_LOADING_DIR)
+ $LOADED_FEATURES << File.expand_path("load_fixture.dylib", CODE_LOADING_DIR)
+ $LOADED_FEATURES << File.expand_path("load_fixture.so", CODE_LOADING_DIR)
+ $LOADED_FEATURES << File.expand_path("load_fixture.dll", CODE_LOADING_DIR)
+ path = File.expand_path "load_fixture", CODE_LOADING_DIR
+ @object.require(path).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "does not load a C-extension file if a .rb extensioned file is already loaded" do
+ $LOADED_FEATURES << File.expand_path("load_fixture.rb", CODE_LOADING_DIR)
+ path = File.expand_path "load_fixture", CODE_LOADING_DIR
+ @object.require(path).should be_false
+ ScratchPad.recorded.should == []
+ end
+
+ it "loads a .rb extensioned file when passed a non-.rb extensioned path" do
+ path = File.expand_path "load_fixture.ext", CODE_LOADING_DIR
+ File.exist?(path).should be_true
+ @object.require(path).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "loads a .rb extensioned file when a complex-extensioned C-extension file of the same name is loaded" do
+ $LOADED_FEATURES << File.expand_path("load_fixture.ext.bundle", CODE_LOADING_DIR)
+ $LOADED_FEATURES << File.expand_path("load_fixture.ext.dylib", CODE_LOADING_DIR)
+ $LOADED_FEATURES << File.expand_path("load_fixture.ext.so", CODE_LOADING_DIR)
+ $LOADED_FEATURES << File.expand_path("load_fixture.ext.dll", CODE_LOADING_DIR)
+ path = File.expand_path "load_fixture.ext", CODE_LOADING_DIR
+ @object.require(path).should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "does not load a C-extension file if a complex-extensioned .rb file is already loaded" do
+ $LOADED_FEATURES << File.expand_path("load_fixture.ext.rb", CODE_LOADING_DIR)
+ path = File.expand_path "load_fixture.ext", CODE_LOADING_DIR
+ @object.require(path).should be_false
+ ScratchPad.recorded.should == []
+ end
+ end
+
+ describe "($LOADED_FEATURES)" do
+ before :each do
+ @path = File.expand_path("load_fixture.rb", CODE_LOADING_DIR)
+ end
+
+ it "stores an absolute path" do
+ @object.require(@path).should be_true
+ $LOADED_FEATURES.should include(@path)
+ end
+
+ it "does not store the path if the load fails" do
+ $LOAD_PATH << CODE_LOADING_DIR
+ saved_loaded_features = $LOADED_FEATURES.dup
+ lambda { @object.require("raise_fixture.rb") }.should raise_error(RuntimeError)
+ $LOADED_FEATURES.should == saved_loaded_features
+ end
+
+ it "does not load an absolute path that is already stored" do
+ $LOADED_FEATURES << @path
+ @object.require(@path).should be_false
+ ScratchPad.recorded.should == []
+ end
+
+ it "does not load a ./ relative path that is already stored" do
+ $LOADED_FEATURES << "./load_fixture.rb"
+ Dir.chdir CODE_LOADING_DIR do
+ @object.require("./load_fixture.rb").should be_false
+ end
+ ScratchPad.recorded.should == []
+ end
+
+ it "does not load a ../ relative path that is already stored" do
+ $LOADED_FEATURES << "../load_fixture.rb"
+ Dir.chdir CODE_LOADING_DIR do
+ @object.require("../load_fixture.rb").should be_false
+ end
+ ScratchPad.recorded.should == []
+ end
+
+ it "does not load a non-canonical path that is already stored" do
+ $LOADED_FEATURES << "code/../code/load_fixture.rb"
+ $LOAD_PATH << File.dirname(CODE_LOADING_DIR)
+ @object.require("code/../code/load_fixture.rb").should be_false
+ ScratchPad.recorded.should == []
+ end
+
+ it "respects being replaced with a new array" do
+ prev = $LOADED_FEATURES.dup
+
+ @object.require(@path).should be_true
+ $LOADED_FEATURES.should include(@path)
+
+ $LOADED_FEATURES.replace(prev)
+
+ $LOADED_FEATURES.should_not include(@path)
+ @object.require(@path).should be_true
+ $LOADED_FEATURES.should include(@path)
+ end
+
+ it "does not load twice the same file with and without extension" do
+ $LOAD_PATH << CODE_LOADING_DIR
+ @object.require("load_fixture.rb").should be_true
+ @object.require("load_fixture").should be_false
+ end
+
+ describe "when a non-extensioned file is in $LOADED_FEATURES" do
+ before :each do
+ $LOADED_FEATURES << "load_fixture"
+ end
+
+ it "loads a .rb extensioned file when a non extensioned file is in $LOADED_FEATURES" do
+ $LOAD_PATH << CODE_LOADING_DIR
+ @object.require("load_fixture").should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "loads a .rb extensioned file from a subdirectory" do
+ $LOAD_PATH << File.dirname(CODE_LOADING_DIR)
+ @object.require("code/load_fixture").should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ it "returns false if the file is not found" do
+ Dir.chdir File.dirname(CODE_LOADING_DIR) do
+ @object.require("load_fixture").should be_false
+ ScratchPad.recorded.should == []
+ end
+ end
+
+ it "returns false when passed a path and the file is not found" do
+ $LOADED_FEATURES << "code/load_fixture"
+ Dir.chdir CODE_LOADING_DIR do
+ @object.require("code/load_fixture").should be_false
+ ScratchPad.recorded.should == []
+ end
+ end
+ end
+
+ it "stores ../ relative paths as absolute paths" do
+ Dir.chdir CODE_LOADING_DIR do
+ @object.require("../code/load_fixture.rb").should be_true
+ end
+ $LOADED_FEATURES.should include(@path)
+ end
+
+ it "stores ./ relative paths as absolute paths" do
+ Dir.chdir CODE_LOADING_DIR do
+ @object.require("./load_fixture.rb").should be_true
+ end
+ $LOADED_FEATURES.should include(@path)
+ end
+
+ it "collapses duplicate path separators" do
+ $LOAD_PATH << "."
+ sep = File::Separator + File::Separator
+ path = ["..", "code", "load_fixture.rb"].join(sep)
+ Dir.chdir CODE_LOADING_DIR do
+ @object.require(path).should be_true
+ end
+ $LOADED_FEATURES.should include(@path)
+ end
+
+ it "canonicalizes non-unique absolute paths" do
+ path = File.join CODE_LOADING_DIR, "..", "code", "load_fixture.rb"
+ @object.require(path).should be_true
+ $LOADED_FEATURES.should include(@path)
+ end
+
+ it "adds the suffix of the resolved filename" do
+ $LOAD_PATH << CODE_LOADING_DIR
+ @object.require("load_fixture").should be_true
+ $LOADED_FEATURES.should include(@path)
+ end
+
+ it "does not load a non-canonical path for a file already loaded" do
+ $LOADED_FEATURES << @path
+ $LOAD_PATH << File.dirname(CODE_LOADING_DIR)
+ @object.require("code/../code/load_fixture.rb").should be_false
+ ScratchPad.recorded.should == []
+ end
+
+ it "does not load a ./ relative path for a file already loaded" do
+ $LOADED_FEATURES << @path
+ $LOAD_PATH << "an_irrelevant_dir"
+ Dir.chdir CODE_LOADING_DIR do
+ @object.require("./load_fixture.rb").should be_false
+ end
+ ScratchPad.recorded.should == []
+ end
+
+ it "does not load a ../ relative path for a file already loaded" do
+ $LOADED_FEATURES << @path
+ $LOAD_PATH << "an_irrelevant_dir"
+ Dir.chdir CODE_LOADING_DIR do
+ @object.require("../code/load_fixture.rb").should be_false
+ end
+ ScratchPad.recorded.should == []
+ end
+
+ ruby_version_is "2.2"..."2.3" do
+ it "complex, enumerator, rational and unicode_normalize are already required" do
+ provided = %w[complex enumerator rational unicode_normalize]
+ features = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems')
+ provided.each { |feature|
+ features.should =~ /\b#{feature}\.(rb|so)$/
+ }
+
+ code = provided.map { |f| "puts require #{f.inspect}\n" }.join
+ required = ruby_exe(code, options: '--disable-gems')
+ required.should == "false\n" * provided.size
+ end
+ end
+
+ ruby_version_is "2.3"..."2.5" do
+ it "complex, enumerator, rational, thread and unicode_normalize are already required" do
+ provided = %w[complex enumerator rational thread unicode_normalize]
+ features = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems')
+ provided.each { |feature|
+ features.should =~ /\b#{feature}\.(rb|so|jar)$/
+ }
+
+ code = provided.map { |f| "puts require #{f.inspect}\n" }.join
+ required = ruby_exe(code, options: '--disable-gems')
+ required.should == "false\n" * provided.size
+ end
+ end
+
+ ruby_version_is "2.5" do
+ it "complex, enumerator, rational and thread are already required" do
+ provided = %w[complex enumerator rational thread]
+ features = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems')
+ provided.each { |feature|
+ features.should =~ /\b#{feature}\.(rb|so|jar)$/
+ }
+
+ code = provided.map { |f| "puts require #{f.inspect}\n" }.join
+ required = ruby_exe(code, options: '--disable-gems')
+ required.should == "false\n" * provided.size
+ end
+ end
+ end
+
+ describe "(shell expansion)" do
+ before :each do
+ @path = File.expand_path("load_fixture.rb", CODE_LOADING_DIR)
+ @env_home = ENV["HOME"]
+ ENV["HOME"] = CODE_LOADING_DIR
+ end
+
+ after :each do
+ ENV["HOME"] = @env_home
+ end
+
+ # "#3171"
+ it "performs tilde expansion on a .rb file before storing paths in $LOADED_FEATURES" do
+ @object.require("~/load_fixture.rb").should be_true
+ $LOADED_FEATURES.should include(@path)
+ end
+
+ it "performs tilde expansion on a non-extensioned file before storing paths in $LOADED_FEATURES" do
+ @object.require("~/load_fixture").should be_true
+ $LOADED_FEATURES.should include(@path)
+ end
+ end
+
+ describe "(concurrently)" do
+ before :each do
+ ScratchPad.record []
+ @path = File.expand_path "concurrent.rb", CODE_LOADING_DIR
+ @path2 = File.expand_path "concurrent2.rb", CODE_LOADING_DIR
+ @path3 = File.expand_path "concurrent3.rb", CODE_LOADING_DIR
+ end
+
+ after :each do
+ ScratchPad.clear
+ $LOADED_FEATURES.delete @path
+ $LOADED_FEATURES.delete @path2
+ $LOADED_FEATURES.delete @path3
+ end
+
+ # Quick note about these specs:
+ #
+ # The behavior we're spec'ing requires that t2 enter #require, see t1 is
+ # loading @path, grab a lock, and wait on it.
+ #
+ # We do make sure that t2 starts the require once t1 is in the middle
+ # of concurrent.rb, but we then need to get t2 to get far enough into #require
+ # to see t1's lock and try to lock it.
+ it "blocks a second thread from returning while the 1st is still requiring" do
+ fin = false
+
+ t1_res = nil
+ t2_res = nil
+
+ t2 = nil
+ t1 = Thread.new do
+ Thread.pass until t2
+ Thread.current[:wait_for] = t2
+ t1_res = @object.require(@path)
+ Thread.pass until fin
+ ScratchPad.recorded << :t1_post
+ end
+
+ t2 = Thread.new do
+ Thread.pass until t1[:in_concurrent_rb]
+ $VERBOSE, @verbose = nil, $VERBOSE
+ begin
+ t2_res = @object.require(@path)
+ ScratchPad.recorded << :t2_post
+ ensure
+ $VERBOSE = @verbose
+ fin = true
+ end
+ end
+
+ t1.join
+ t2.join
+
+ t1_res.should be_true
+ t2_res.should be_false
+
+ ScratchPad.recorded.should == [:con_pre, :con_post, :t2_post, :t1_post]
+ end
+
+ it "blocks based on the path" do
+ t1_res = nil
+ t2_res = nil
+
+ t2 = nil
+ t1 = Thread.new do
+ Thread.pass until t2
+ Thread.current[:concurrent_require_thread] = t2
+ t1_res = @object.require(@path2)
+ end
+
+ t2 = Thread.new do
+ Thread.pass until t1[:in_concurrent_rb2]
+ t2_res = @object.require(@path3)
+ end
+
+ t1.join
+ t2.join
+
+ t1_res.should be_true
+ t2_res.should be_true
+
+ ScratchPad.recorded.should == [:con2_pre, :con3, :con2_post]
+ end
+
+ it "allows a 2nd require if the 1st raised an exception" do
+ fin = false
+
+ t2_res = nil
+
+ t2 = nil
+ t1 = Thread.new do
+ Thread.pass until t2
+ Thread.current[:wait_for] = t2
+ Thread.current[:con_raise] = true
+
+ lambda {
+ @object.require(@path)
+ }.should raise_error(RuntimeError)
+
+ Thread.pass until fin
+ ScratchPad.recorded << :t1_post
+ end
+
+ t2 = Thread.new do
+ Thread.pass until t1[:in_concurrent_rb]
+ $VERBOSE, @verbose = nil, $VERBOSE
+ begin
+ t2_res = @object.require(@path)
+ ScratchPad.recorded << :t2_post
+ ensure
+ $VERBOSE = @verbose
+ fin = true
+ end
+ end
+
+ t1.join
+ t2.join
+
+ t2_res.should be_true
+
+ ScratchPad.recorded.should == [:con_pre, :con_pre, :con_post, :t2_post, :t1_post]
+ end
+
+ # "redmine #5754"
+ it "blocks a 3rd require if the 1st raises an exception and the 2nd is still running" do
+ fin = false
+
+ t1_res = nil
+ t2_res = nil
+
+ raised = false
+
+ t2 = nil
+ t1 = Thread.new do
+ Thread.current[:con_raise] = true
+
+ lambda {
+ @object.require(@path)
+ }.should raise_error(RuntimeError)
+
+ raised = true
+
+ # This hits the bug. Because MRI removes its internal lock from a table
+ # when the exception is raised, this #require doesn't see that t2 is in
+ # the middle of requiring the file, so this #require runs when it should not.
+ Thread.pass until t2 && t2[:in_concurrent_rb]
+ t1_res = @object.require(@path)
+
+ Thread.pass until fin
+ ScratchPad.recorded << :t1_post
+ end
+
+ t2 = Thread.new do
+ Thread.pass until raised
+ Thread.current[:wait_for] = t1
+ begin
+ t2_res = @object.require(@path)
+ ScratchPad.recorded << :t2_post
+ ensure
+ fin = true
+ end
+ end
+
+ t1.join
+ t2.join
+
+ t1_res.should be_false
+ t2_res.should be_true
+
+ ScratchPad.recorded.should == [:con_pre, :con_pre, :con_post, :t2_post, :t1_post]
+ end
+ end
+
+ it "stores the missing path in a LoadError object" do
+ path = "abcd1234"
+
+ lambda {
+ @object.send(@method, path)
+ }.should raise_error(LoadError) { |e|
+ e.path.should == path
+ }
+ end
+end
diff --git a/spec/rubyspec/core/kernel/singleton_class_spec.rb b/spec/rubyspec/core/kernel/singleton_class_spec.rb
new file mode 100644
index 0000000000..b5e0703905
--- /dev/null
+++ b/spec/rubyspec/core/kernel/singleton_class_spec.rb
@@ -0,0 +1,27 @@
+describe "Kernel#singleton_class" do
+ it "returns class extended from an object" do
+ x = Object.new
+ xs = class << x; self; end
+ xs.should == x.singleton_class
+ end
+
+ it "returns NilClass for nil" do
+ nil.singleton_class.should == NilClass
+ end
+
+ it "returns TrueClass for true" do
+ true.singleton_class.should == TrueClass
+ end
+
+ it "returns FalseClass for false" do
+ false.singleton_class.should == FalseClass
+ end
+
+ it "raises TypeError for Fixnum" do
+ lambda { 123.singleton_class }.should raise_error(TypeError)
+ end
+
+ it "raises TypeError for Symbol" do
+ lambda { :foo.singleton_class }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/singleton_methods_spec.rb b/spec/rubyspec/core/kernel/singleton_methods_spec.rb
new file mode 100644
index 0000000000..596e5ddad2
--- /dev/null
+++ b/spec/rubyspec/core/kernel/singleton_methods_spec.rb
@@ -0,0 +1,180 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../../../fixtures/reflection', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe :kernel_singleton_methods, shared: true do
+ it "returns an empty Array for an object with no singleton methods" do
+ ReflectSpecs.o.singleton_methods(*@object).should == []
+ end
+
+ it "returns the names of module methods for a module" do
+ ReflectSpecs::M.singleton_methods(*@object).should include(:ms_pro, :ms_pub)
+ end
+
+ it "does not return private module methods for a module" do
+ ReflectSpecs::M.singleton_methods(*@object).should_not include(:ms_pri)
+ end
+
+ it "returns the names of class methods for a class" do
+ ReflectSpecs::A.singleton_methods(*@object).should include(:as_pro, :as_pub)
+ end
+
+ it "does not return private class methods for a class" do
+ ReflectSpecs::A.singleton_methods(*@object).should_not include(:as_pri)
+ end
+
+ it "returns the names of singleton methods for an object" do
+ ReflectSpecs.os.singleton_methods(*@object).should include(:os_pro, :os_pub)
+ end
+end
+
+describe :kernel_singleton_methods_modules, shared: true do
+ it "does not return any included methods for a module including a module" do
+ ReflectSpecs::N.singleton_methods(*@object).should include(:ns_pro, :ns_pub)
+ end
+
+ it "does not return any included methods for a class including a module" do
+ ReflectSpecs::D.singleton_methods(*@object).should include(:ds_pro, :ds_pub)
+ end
+end
+
+describe :kernel_singleton_methods_supers, shared: true do
+ it "returns the names of singleton methods for an object extented with a module" do
+ ReflectSpecs.oe.singleton_methods(*@object).should include(:m_pro, :m_pub)
+ end
+
+ it "returns a unique list for an object extended with a module" do
+ m = ReflectSpecs.oed.singleton_methods(*@object)
+ r = m.select { |x| x == :pub or x == :pro }.sort
+ r.should == [:pro, :pub]
+ end
+
+ it "returns the names of singleton methods for an object extented with two modules" do
+ ReflectSpecs.oee.singleton_methods(*@object).should include(:m_pro, :m_pub, :n_pro, :n_pub)
+ end
+
+ it "returns the names of singleton methods for an object extented with a module including a module" do
+ ReflectSpecs.oei.singleton_methods(*@object).should include(:n_pro, :n_pub, :m_pro, :m_pub)
+ end
+
+ it "returns the names of inherited singleton methods for a subclass" do
+ ReflectSpecs::B.singleton_methods(*@object).should include(:as_pro, :as_pub, :bs_pro, :bs_pub)
+ end
+
+ it "returns a unique list for a subclass" do
+ m = ReflectSpecs::B.singleton_methods(*@object)
+ r = m.select { |x| x == :pub or x == :pro }.sort
+ r.should == [:pro, :pub]
+ end
+
+ it "returns the names of inherited singleton methods for a subclass including a module" do
+ ReflectSpecs::C.singleton_methods(*@object).should include(:as_pro, :as_pub, :cs_pro, :cs_pub)
+ end
+
+ it "returns a unique list for a subclass including a module" do
+ m = ReflectSpecs::C.singleton_methods(*@object)
+ r = m.select { |x| x == :pub or x == :pro }.sort
+ r.should == [:pro, :pub]
+ end
+
+ it "returns the names of inherited singleton methods for a subclass of a class including a module" do
+ ReflectSpecs::E.singleton_methods(*@object).should include(:ds_pro, :ds_pub, :es_pro, :es_pub)
+ end
+
+ it "returns the names of inherited singleton methods for a subclass of a class that includes a module, where the subclass also includes a module" do
+ ReflectSpecs::F.singleton_methods(*@object).should include(:ds_pro, :ds_pub, :fs_pro, :fs_pub)
+ end
+
+ it "returns the names of inherited singleton methods for a class extended with a module" do
+ ReflectSpecs::P.singleton_methods(*@object).should include(:m_pro, :m_pub)
+ end
+end
+
+describe :kernel_singleton_methods_private_supers, shared: true do
+ it "does not return private singleton methods for an object extended with a module" do
+ ReflectSpecs.oe.singleton_methods(*@object).should_not include(:m_pri)
+ end
+
+ it "does not return private singleton methods for an object extended with two modules" do
+ ReflectSpecs.oee.singleton_methods(*@object).should_not include(:m_pri)
+ end
+
+ it "does not return private singleton methods for an object extented with a module including a module" do
+ ReflectSpecs.oei.singleton_methods(*@object).should_not include(:n_pri, :m_pri)
+ end
+
+ it "does not return private singleton methods for a class extended with a module" do
+ ReflectSpecs::P.singleton_methods(*@object).should_not include(:m_pri)
+ end
+
+ it "does not return private inherited singleton methods for a module including a module" do
+ ReflectSpecs::N.singleton_methods(*@object).should_not include(:ns_pri)
+ end
+
+ it "does not return private inherited singleton methods for a class including a module" do
+ ReflectSpecs::D.singleton_methods(*@object).should_not include(:ds_pri)
+ end
+
+ it "does not return private inherited singleton methods for a subclass" do
+ ReflectSpecs::B.singleton_methods(*@object).should_not include(:as_pri, :bs_pri)
+ end
+
+ it "does not return private inherited singleton methods for a subclass including a module" do
+ ReflectSpecs::C.singleton_methods(*@object).should_not include(:as_pri, :cs_pri)
+ end
+
+ it "does not return private inherited singleton methods for a subclass of a class including a module" do
+ ReflectSpecs::E.singleton_methods(*@object).should_not include(:ds_pri, :es_pri)
+ end
+
+ it "does not return private inherited singleton methods for a subclass of a class that includes a module, where the subclass also includes a module" do
+ ReflectSpecs::F.singleton_methods(*@object).should_not include(:ds_pri, :fs_pri)
+ end
+end
+
+describe "Kernel#singleton_methods" do
+ describe "when not passed an argument" do
+ it_behaves_like :kernel_singleton_methods, nil, []
+ it_behaves_like :kernel_singleton_methods_supers, nil, []
+ it_behaves_like :kernel_singleton_methods_modules, nil, []
+ it_behaves_like :kernel_singleton_methods_private_supers, nil, []
+ end
+
+ describe "when passed true" do
+ it_behaves_like :kernel_singleton_methods, nil, true
+ it_behaves_like :kernel_singleton_methods_supers, nil, true
+ it_behaves_like :kernel_singleton_methods_modules, nil, true
+ it_behaves_like :kernel_singleton_methods_private_supers, nil, true
+
+ end
+
+ describe "when passed false" do
+ it_behaves_like :kernel_singleton_methods, nil, false
+ it_behaves_like :kernel_singleton_methods_modules, nil, false
+ it_behaves_like :kernel_singleton_methods_private_supers, nil, false
+
+ it "returns an empty Array for an object extented with a module" do
+ ReflectSpecs.oe.singleton_methods(false).should == []
+ end
+
+ it "returns an empty Array for an object extented with two modules" do
+ ReflectSpecs.oee.singleton_methods(false).should == []
+ end
+
+ it "returns an empty Array for an object extended with a module including a module" do
+ ReflectSpecs.oei.singleton_methods(false).should == []
+ end
+
+ it "returns the names of singleton methods of the subclass" do
+ ReflectSpecs::B.singleton_methods(false).should include(:bs_pro, :bs_pub)
+ end
+
+ it "does not return names of inherited singleton methods for a subclass" do
+ ReflectSpecs::B.singleton_methods(false).should_not include(:as_pro, :as_pub)
+ end
+
+ it "does not return the names of inherited singleton methods for a class extended with a module" do
+ ReflectSpecs::P.singleton_methods(false).should_not include(:m_pro, :m_pub)
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/sleep_spec.rb b/spec/rubyspec/core/kernel/sleep_spec.rb
new file mode 100644
index 0000000000..bcb0060aa3
--- /dev/null
+++ b/spec/rubyspec/core/kernel/sleep_spec.rb
@@ -0,0 +1,52 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#sleep" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:sleep)
+ end
+
+ it "accepts a Float" do
+ sleep(0.1).should be_close(0, 2)
+ end
+
+ it "accepts a Fixnum" do
+ sleep(0).should be_close(0, 2)
+ end
+
+ it "accepts a Rational" do
+ sleep(Rational(1, 9)).should be_close(0, 2)
+ end
+
+ it "raises an ArgumentError when passed a negative duration" do
+ lambda { sleep(-0.1) }.should raise_error(ArgumentError)
+ lambda { sleep(-1) }.should raise_error(ArgumentError)
+ end
+
+ it "raises a TypeError when passed nil" do
+ lambda { sleep(nil) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError when passed a String" do
+ lambda { sleep('2') }.should raise_error(TypeError)
+ end
+
+ it "pauses execution indefinitely if not given a duration" do
+ running = false
+ t = Thread.new do
+ running = true
+ sleep
+ 5
+ end
+
+ Thread.pass until running
+ Thread.pass while t.status and t.status != "sleep"
+
+ t.wakeup
+ t.value.should == 5
+ end
+end
+
+describe "Kernel.sleep" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/spawn_spec.rb b/spec/rubyspec/core/kernel/spawn_spec.rb
new file mode 100644
index 0000000000..ad937b17dd
--- /dev/null
+++ b/spec/rubyspec/core/kernel/spawn_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+# These specs only run a basic usage of #spawn.
+# Process.spawn has more complete specs and they are not
+# run here as it is redundant and takes too long for little gain.
+describe "Kernel#spawn" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:spawn)
+ end
+
+ it "executes the given command" do
+ lambda {
+ Process.wait spawn("echo spawn")
+ }.should output_to_fd("spawn\n")
+ end
+end
+
+describe "Kernel.spawn" do
+ it "executes the given command" do
+ lambda {
+ Process.wait Kernel.spawn("echo spawn")
+ }.should output_to_fd("spawn\n")
+ end
+end
diff --git a/spec/rubyspec/core/kernel/sprintf_spec.rb b/spec/rubyspec/core/kernel/sprintf_spec.rb
new file mode 100644
index 0000000000..984f31dc7f
--- /dev/null
+++ b/spec/rubyspec/core/kernel/sprintf_spec.rb
@@ -0,0 +1,310 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#sprintf" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:sprintf)
+ end
+
+ it "treats nil arguments as zero-width strings in %s slots" do
+ sprintf("%s%d%s%s", nil, 4, 'a', 'b').should == '4ab'
+ end
+
+ it "passes some tests for positive %x" do
+ sprintf("%x", 123).should == "7b"
+ sprintf("%0x", 123).should == "7b"
+ sprintf("% x", 123).should == " 7b"
+ sprintf("%+x", 123).should == "+7b"
+ sprintf("%+0x", 123).should == "+7b"
+ sprintf("%+ x", 123).should == "+7b"
+ sprintf("% 0x", 123).should == " 7b"
+
+ sprintf("%#x", 123).should == "0x7b"
+ sprintf("%#0x", 123).should == "0x7b"
+ sprintf("%# x", 123).should == " 0x7b"
+ sprintf("%#+x", 123).should == "+0x7b"
+ sprintf("%#+0x", 123).should == "+0x7b"
+ sprintf("%#+ x", 123).should == "+0x7b"
+ sprintf("%# 0x", 123).should == " 0x7b"
+
+ sprintf("%8x", 123).should == " 7b"
+ sprintf("%08x", 123).should == "0000007b"
+ sprintf("% 8x", 123).should == " 7b"
+ sprintf("%+8x", 123).should == " +7b"
+ sprintf("%+08x", 123).should == "+000007b"
+ sprintf("%+ 8x", 123).should == " +7b"
+ sprintf("% 08x", 123).should == " 000007b"
+
+ sprintf("%#8x", 123).should == " 0x7b"
+ sprintf("%#08x", 123).should == "0x00007b"
+ sprintf("%# 8x", 123).should == " 0x7b"
+ sprintf("%#+8x", 123).should == " +0x7b"
+ sprintf("%#+08x", 123).should == "+0x0007b"
+ sprintf("%#+ 8x", 123).should == " +0x7b"
+ sprintf("%# 08x", 123).should == " 0x0007b"
+
+ sprintf("%8.10x", 123).should == "000000007b"
+ sprintf("%08.10x", 123).should == "000000007b"
+ sprintf("% 8.10x", 123).should == " 000000007b"
+ sprintf("%+8.10x", 123).should == "+000000007b"
+ sprintf("%+08.10x", 123).should == "+000000007b"
+ sprintf("%+ 8.10x", 123).should == "+000000007b"
+ sprintf("% 08.10x", 123).should == " 000000007b"
+
+ sprintf("%10.8x", 123).should == " 0000007b"
+ sprintf("%010.8x", 123).should == " 0000007b"
+ sprintf("% 10.8x", 123).should == " 0000007b"
+ sprintf("%+10.8x", 123).should == " +0000007b"
+ sprintf("%+010.8x", 123).should == " +0000007b"
+ sprintf("%+ 10.8x", 123).should == " +0000007b"
+ sprintf("% 010.8x", 123).should == " 0000007b"
+ end
+
+ describe "with format string that contains %{} sections" do
+ it "substitutes values for named references" do
+ sprintf("%{foo}f", {foo: 1}).should == "1f"
+ end
+
+ it "raises KeyError when no matching key is in second argument" do
+ lambda { sprintf("%{foo}f", {}) }.should raise_error(KeyError)
+ end
+ end
+
+ describe "with format string that contains %<> sections" do
+ it "formats values for named references" do
+ sprintf("%<foo>f", {foo: 1}).should == "1.000000"
+ end
+
+ it "raises KeyError when no matching key is in second argument" do
+ lambda { sprintf("%<foo>f", {}) }.should raise_error(KeyError)
+ end
+
+ it "raises ArgumentError if missing second named argument" do
+ lambda { sprintf("%<key><foo>d", {key: 1}) }.should raise_error(ArgumentError)
+ end
+ end
+
+ describe "with negative values" do
+ describe "with format %x" do
+ it "precedes the number with '..'" do
+ sprintf("%0x", -123).should == "..f85"
+ sprintf("%#0x", -123).should == "0x..f85"
+ sprintf("%08x", -123).should == "..ffff85"
+ sprintf("%#08x", -123).should == "0x..ff85"
+ sprintf("%8.10x", -123).should == "..ffffff85"
+ sprintf("%08.10x", -123).should == "..ffffff85"
+ sprintf("%10.8x", -123).should == " ..ffff85"
+ sprintf("%010.8x", -123).should == " ..ffff85"
+ end
+ end
+
+ describe "with format %b or %B" do
+ it "precedes the number with '..'" do
+ sprintf("%.7b", -5).should == "..11011"
+ sprintf("%.7B", -5).should == "..11011"
+ sprintf("%0b", -5).should == "..1011"
+ end
+ end
+ end
+
+ it "passes some tests for negative %x" do
+ sprintf("%x", -123).should == "..f85"
+ sprintf("% x", -123).should == "-7b"
+ sprintf("%+x", -123).should == "-7b"
+ sprintf("%+0x", -123).should == "-7b"
+ sprintf("%+ x", -123).should == "-7b"
+ sprintf("% 0x", -123).should == "-7b"
+
+ sprintf("%#x", -123).should == "0x..f85"
+ sprintf("%# x", -123).should == "-0x7b"
+ sprintf("%#+x", -123).should == "-0x7b"
+ sprintf("%#+0x", -123).should == "-0x7b"
+ sprintf("%#+ x", -123).should == "-0x7b"
+ sprintf("%# 0x", -123).should == "-0x7b"
+
+ sprintf("%8x", -123).should == " ..f85"
+ sprintf("% 8x", -123).should == " -7b"
+ sprintf("%+8x", -123).should == " -7b"
+ sprintf("%+08x", -123).should == "-000007b"
+ sprintf("%+ 8x", -123).should == " -7b"
+ sprintf("% 08x", -123).should == "-000007b"
+
+ sprintf("%#8x", -123).should == " 0x..f85"
+ sprintf("%# 8x", -123).should == " -0x7b"
+ sprintf("%#+8x", -123).should == " -0x7b"
+ sprintf("%#+08x", -123).should == "-0x0007b"
+ sprintf("%#+ 8x", -123).should == " -0x7b"
+ sprintf("%# 08x", -123).should == "-0x0007b"
+
+ sprintf("% 8.10x", -123).should == "-000000007b"
+ sprintf("%+8.10x", -123).should == "-000000007b"
+ sprintf("%+08.10x", -123).should == "-000000007b"
+ sprintf("%+ 8.10x", -123).should == "-000000007b"
+ sprintf("% 08.10x", -123).should == "-000000007b"
+
+ sprintf("% 10.8x", -123).should == " -0000007b"
+ sprintf("%+10.8x", -123).should == " -0000007b"
+ sprintf("%+010.8x", -123).should == " -0000007b"
+ sprintf("%+ 10.8x", -123).should == " -0000007b"
+ sprintf("% 010.8x", -123).should == " -0000007b"
+ end
+
+ it "passes some tests for negative %u" do
+ sprintf("%u", -123).should == "-123"
+ sprintf("%0u", -123).should == "-123"
+ sprintf("%#u", -123).should == "-123"
+ sprintf("%#0u", -123).should == "-123"
+ sprintf("%8u", -123).should == " -123"
+ sprintf("%08u", -123).should == "-0000123"
+ sprintf("%#8u", -123).should == " -123"
+ sprintf("%#08u", -123).should == "-0000123"
+
+ sprintf("%30u", -123).should == " -123"
+ sprintf("%030u", -123).should == "-00000000000000000000000000123"
+
+ sprintf("%#30u", -123).should == " -123"
+ sprintf("%#030u", -123).should == "-00000000000000000000000000123"
+
+ sprintf("%24.30u", -123).should == "-000000000000000000000000000123"
+ sprintf("%024.30u", -123).should == "-000000000000000000000000000123"
+
+ sprintf("%#24.30u", -123).should == "-000000000000000000000000000123"
+ sprintf("%#024.30u", -123).should == "-000000000000000000000000000123"
+
+
+ sprintf("%30.24u", -123).should == " -000000000000000000000123"
+ sprintf("%030.24u", -123).should == " -000000000000000000000123"
+
+ sprintf("%#30.24u", -123).should == " -000000000000000000000123"
+ sprintf("%#030.24u", -123).should == " -000000000000000000000123"
+ end
+
+ it "passes some tests for positive %u" do
+ sprintf("%30u", 123).should == " 123"
+ sprintf("%030u", 123).should == "000000000000000000000000000123"
+
+ sprintf("%#30u", 123).should == " 123"
+ sprintf("%#030u", 123).should == "000000000000000000000000000123"
+
+ sprintf("%24.30u", 123).should == "000000000000000000000000000123"
+ sprintf("%024.30u", 123).should == "000000000000000000000000000123"
+
+ sprintf("%#24.30u", 123).should == "000000000000000000000000000123"
+ sprintf("%#024.30u", 123).should == "000000000000000000000000000123"
+
+ sprintf("%30.24u", 123).should == " 000000000000000000000123"
+ sprintf("%030.24u", 123).should == " 000000000000000000000123"
+
+ sprintf("%#30.24u", 123).should == " 000000000000000000000123"
+ sprintf("%#030.24u", 123).should == " 000000000000000000000123"
+ end
+
+ it "passes some tests for positive %d" do
+ sprintf("%30d", 123).should == " 123"
+ sprintf("%030d", 123).should == "000000000000000000000000000123"
+
+ sprintf("%#30d", 123).should == " 123"
+ sprintf("%#030d", 123).should == "000000000000000000000000000123"
+
+ sprintf("%24.30d", 123).should == "000000000000000000000000000123"
+ sprintf("%024.30d", 123).should == "000000000000000000000000000123"
+
+ sprintf("%#24.30d", 123).should == "000000000000000000000000000123"
+ sprintf("%#024.30d", 123).should == "000000000000000000000000000123"
+
+ sprintf("%30.24d", 123).should == " 000000000000000000000123"
+ sprintf("%030.24d", 123).should == " 000000000000000000000123"
+
+ sprintf("%#30.24d", 123).should == " 000000000000000000000123"
+ sprintf("%#030.24d", 123).should == " 000000000000000000000123"
+ end
+
+ it "passes some tests for positive %f" do
+ sprintf("%30f", 123.1).should == " 123.100000"
+ sprintf("%030f", 123.1).should == "00000000000000000000123.100000"
+
+ sprintf("%#30f", 123.1).should == " 123.100000"
+ sprintf("%#030f", 123.1).should == "00000000000000000000123.100000"
+
+ sprintf("%10.4f", 123.1).should == " 123.1000"
+ sprintf("%010.4f", 123.1).should == "00123.1000"
+
+ sprintf("%10.0f", 123.1).should == " 123"
+ sprintf("%010.0f", 123.1).should == "0000000123"
+ end
+
+ it "passes some tests for negative %f" do
+ sprintf("%30f", -123.5).should == " -123.500000"
+ sprintf("%030f", -123.5).should == "-0000000000000000000123.500000"
+
+ sprintf("%#30f", -123.5).should == " -123.500000"
+ sprintf("%#030f", -123.5).should == "-0000000000000000000123.500000"
+
+ sprintf("%10.4f", -123.5).should == " -123.5000"
+ sprintf("%010.4f", -123.5).should == "-0123.5000"
+
+ sprintf("%10.0f", -123.5).should == " -124"
+ sprintf("%010.0f", -123.5).should == "-000000124"
+ end
+
+ it "passes some tests for infinite and nan" do
+ sprintf("%f", Float::INFINITY).should == "Inf"
+ sprintf("%f", -Float::INFINITY).should == "-Inf"
+ sprintf("%f", Float::NAN).should == "NaN"
+
+ sprintf("%10f", Float::INFINITY).should == " Inf"
+ sprintf("%10f", -Float::INFINITY).should == " -Inf"
+ sprintf("%10f", Float::NAN).should == " NaN"
+ end
+
+ it "passes kstephens's tests" do
+ sprintf("%*1$.*2$3$d", 10, 5, 1).should == " 00001"
+ sprintf("%b", 0).should == "0"
+ sprintf("%B", 0).should == "0"
+ sprintf("%b", -5).should == "..1011"
+ sprintf("%B", -5).should == "..1011"
+ sprintf("%+b", -5).should == "-101"
+ sprintf("%+b", 10).should == "+1010"
+ sprintf("%+b", 0).should == "+0"
+ sprintf("%+o", -5).should == "-5"
+ sprintf("%+o", 10).should == "+12"
+ sprintf("%+o", 0).should == "+0"
+ sprintf("%+d", -5).should == "-5"
+ sprintf("%+d", 10).should == "+10"
+ sprintf("%+d", 0).should == "+0"
+ sprintf("%+x", -15).should == "-f"
+ sprintf("%+x", 100).should == "+64"
+ sprintf("%+x", 0).should == "+0"
+ sprintf("%+X", -15).should == "-F"
+ sprintf("%+X", 100).should == "+64"
+ sprintf("%+X", 0).should == "+0"
+ sprintf("=%02X", 1).should == "=01"
+ sprintf("%+03d", 0).should == "+00"
+ sprintf("%+03d", 5).should == "+05"
+ sprintf("%+03d", -5).should == "-05"
+ sprintf("%+03d", 12).should == "+12"
+ sprintf("%+03d", -12).should == "-12"
+ sprintf("%+03d", 123).should == "+123"
+ sprintf("%+03d", -123).should == "-123"
+ end
+
+ with_feature :encoding do
+ it "returns a String in the same encoding as the format String if compatible" do
+ format = "%.2f %4s".force_encoding(Encoding::KOI8_U)
+ result = sprintf(format, 1.2, "dogs")
+ result.encoding.should equal(Encoding::KOI8_U)
+ end
+
+ it "returns a String in the argument encoding if format encoding is more restrictive" do
+ format = "foo %s".force_encoding(Encoding::US_ASCII)
+ arg = "b\303\274r".force_encoding(Encoding::UTF_8)
+
+ result = sprintf(format, arg)
+ result.encoding.should equal(Encoding::UTF_8)
+ end
+ end
+end
+
+describe "Kernel.sprintf" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/srand_spec.rb b/spec/rubyspec/core/kernel/srand_spec.rb
new file mode 100644
index 0000000000..33f99f5ac4
--- /dev/null
+++ b/spec/rubyspec/core/kernel/srand_spec.rb
@@ -0,0 +1,61 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel.srand" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:srand)
+ end
+
+ it "returns the previous seed value" do
+ srand(10)
+ srand(20).should == 10
+ end
+
+ it "seeds the RNG correctly and repeatably" do
+ srand(10)
+ x = rand
+ srand(10)
+ rand.should == x
+ end
+
+ it "defaults number to a random value" do
+ lambda { srand }.should_not raise_error
+ srand.should_not == 0
+ end
+
+ it "accepts and uses a seed of 0" do
+ srand(0)
+ srand.should == 0
+ end
+
+ it "accepts a negative seed" do
+ srand(-17)
+ srand.should == -17
+ end
+
+ it "accepts a Bignum as a seed" do
+ srand(0x12345678901234567890)
+ srand.should == 0x12345678901234567890
+ end
+
+ it "calls #to_int on seed" do
+ srand(3.8)
+ srand.should == 3
+
+ s = mock('seed')
+ s.should_receive(:to_int).and_return 0
+ srand(s)
+ end
+
+ it "raises a TypeError when passed nil" do
+ lambda { srand(nil) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError when passed a String" do
+ lambda { srand("7") }.should raise_error(TypeError)
+ end
+end
+
+describe "Kernel#srand" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/sub_spec.rb b/spec/rubyspec/core/kernel/sub_spec.rb
new file mode 100644
index 0000000000..78e5eec4a8
--- /dev/null
+++ b/spec/rubyspec/core/kernel/sub_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+# FIXME: These methods exist only when the -n or -p option is passed to
+# ruby, but we currently don't have a way of specifying that.
+ruby_version_is ""..."1.9" do
+ describe "Kernel#sub" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:sub)
+ end
+ end
+
+ describe "Kernel#sub!" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:sub!)
+ end
+ end
+
+ describe "Kernel.sub" do
+ it "needs to be reviewed for spec completeness"
+ end
+
+ describe "Kernel.sub!" do
+ it "needs to be reviewed for spec completeness"
+ end
+end
diff --git a/spec/rubyspec/core/kernel/syscall_spec.rb b/spec/rubyspec/core/kernel/syscall_spec.rb
new file mode 100644
index 0000000000..bcea833f1f
--- /dev/null
+++ b/spec/rubyspec/core/kernel/syscall_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#syscall" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:syscall)
+ end
+end
+
+describe "Kernel.syscall" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/system_spec.rb b/spec/rubyspec/core/kernel/system_spec.rb
new file mode 100644
index 0000000000..ccbd43cfde
--- /dev/null
+++ b/spec/rubyspec/core/kernel/system_spec.rb
@@ -0,0 +1,107 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe :kernel_system, shared: true do
+ it "executes the specified command in a subprocess" do
+ lambda { @object.system("echo a") }.should output_to_fd("a\n")
+
+ $?.should be_an_instance_of Process::Status
+ $?.success?.should == true
+ end
+
+ it "returns true when the command exits with a zero exit status" do
+ @object.system(ruby_cmd('exit 0')).should == true
+
+ $?.should be_an_instance_of Process::Status
+ $?.success?.should == true
+ $?.exitstatus.should == 0
+ end
+
+ it "returns false when the command exits with a non-zero exit status" do
+ @object.system(ruby_cmd('exit 1')).should == false
+
+ $?.should be_an_instance_of Process::Status
+ $?.success?.should == false
+ $?.exitstatus.should == 1
+ end
+
+ it "returns nil when command execution fails" do
+ @object.system("sad").should be_nil
+
+ $?.should be_an_instance_of Process::Status
+ $?.pid.should be_kind_of(Integer)
+ $?.exitstatus.should == 127
+ end
+
+ it "does not write to stderr when command execution fails" do
+ lambda { @object.system("sad") }.should output_to_fd("", STDERR)
+ end
+
+ platform_is_not :windows do
+ before :each do
+ @shell = ENV['SHELL']
+ end
+
+ before :each do
+ ENV['SHELL'] = @shell
+ end
+
+ it "executes with `sh` if the command contains shell characters" do
+ lambda { @object.system("echo $0") }.should output_to_fd("sh\n")
+ end
+
+ it "ignores SHELL env var and always uses `sh`" do
+ ENV['SHELL'] = "/bin/zsh"
+ lambda { @object.system("echo $0") }.should output_to_fd("sh\n")
+ end
+ end
+
+ before :each do
+ ENV['TEST_SH_EXPANSION'] = 'foo'
+ @shell_var = '$TEST_SH_EXPANSION'
+ platform_is :windows do
+ @shell_var = '%TEST_SH_EXPANSION%'
+ end
+ end
+
+ after :each do
+ ENV.delete('TEST_SH_EXPANSION')
+ end
+
+ it "expands shell variables when given a single string argument" do
+ lambda { @object.system("echo #{@shell_var}") }.should output_to_fd("foo\n")
+ end
+
+ platform_is_not :windows do
+ it "does not expand shell variables when given multiples arguments" do
+ lambda { @object.system("echo", @shell_var) }.should output_to_fd("#{@shell_var}\n")
+ end
+ end
+
+ platform_is :windows do
+ it "does expand shell variables when given multiples arguments" do
+ # See https://bugs.ruby-lang.org/issues/12231
+ lambda { @object.system("echo", @shell_var) }.should output_to_fd("foo\n")
+ end
+ end
+
+ platform_is :windows do
+ it "runs commands starting with any number of @ using shell" do
+ `#{ruby_cmd("p system 'does_not_exist'")} 2>NUL`.chomp.should == "nil"
+ @object.system('@does_not_exist 2>NUL').should == false
+ @object.system("@@@#{ruby_cmd('exit 0')}").should == true
+ end
+ end
+end
+
+describe "Kernel#system" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:system)
+ end
+
+ it_behaves_like :kernel_system, :system, KernelSpecs::Method.new
+end
+
+describe "Kernel.system" do
+ it_behaves_like :kernel_system, :system, Kernel
+end
diff --git a/spec/rubyspec/core/kernel/taint_spec.rb b/spec/rubyspec/core/kernel/taint_spec.rb
new file mode 100644
index 0000000000..0c2fb3286b
--- /dev/null
+++ b/spec/rubyspec/core/kernel/taint_spec.rb
@@ -0,0 +1,45 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#taint" do
+ it "returns self" do
+ o = Object.new
+ o.taint.should equal(o)
+ end
+
+ it "sets the tainted bit" do
+ o = Object.new
+ o.taint
+ o.tainted?.should == true
+ end
+
+ it "raises RuntimeError on an untainted, frozen object" do
+ o = Object.new.freeze
+ lambda { o.taint }.should raise_error(RuntimeError)
+ end
+
+ it "does not raise an error on a tainted, frozen object" do
+ o = Object.new.taint.freeze
+ o.taint.should equal(o)
+ end
+
+ it "has no effect on immediate values" do
+ [nil, true, false].each do |v|
+ v.taint
+ v.tainted?.should == false
+ end
+ end
+
+ it "no raises a RuntimeError on symbols" do
+ v = :sym
+ lambda { v.taint }.should_not raise_error(RuntimeError)
+ v.tainted?.should == false
+ end
+
+ it "no raises error on fixnum values" do
+ [1].each do |v|
+ lambda { v.taint }.should_not raise_error(RuntimeError)
+ v.tainted?.should == false
+ end
+ end
+end
diff --git a/spec/rubyspec/core/kernel/tainted_spec.rb b/spec/rubyspec/core/kernel/tainted_spec.rb
new file mode 100644
index 0000000000..efb31be9d8
--- /dev/null
+++ b/spec/rubyspec/core/kernel/tainted_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#tainted?" do
+ it "returns true if Object is tainted" do
+ o = mock('o')
+ p = mock('p')
+ p.taint
+ o.tainted?.should == false
+ p.tainted?.should == true
+ end
+end
diff --git a/spec/rubyspec/core/kernel/tap_spec.rb b/spec/rubyspec/core/kernel/tap_spec.rb
new file mode 100644
index 0000000000..312a34426c
--- /dev/null
+++ b/spec/rubyspec/core/kernel/tap_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#tap" do
+ it "always yields self and returns self" do
+ a = KernelSpecs::A.new
+ a.tap{|o| o.should equal(a); 42}.should equal(a)
+ end
+
+ it "raises a LocalJumpError when no block given" do
+ lambda { 3.tap }.should raise_error(LocalJumpError)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/test_spec.rb b/spec/rubyspec/core/kernel/test_spec.rb
new file mode 100644
index 0000000000..21d338ed07
--- /dev/null
+++ b/spec/rubyspec/core/kernel/test_spec.rb
@@ -0,0 +1,98 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#test" do
+ before :all do
+ @file = File.dirname(__FILE__) + '/fixtures/classes.rb'
+ @dir = File.dirname(__FILE__) + '/fixtures'
+ end
+
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:test)
+ end
+
+ it "returns true when passed ?f if the argument is a regular file" do
+ Kernel.test(?f, @file).should == true
+ end
+
+ it "returns true when passed ?e if the argument is a file" do
+ Kernel.test(?e, @file).should == true
+ end
+
+ it "returns true when passed ?d if the argument is a directory" do
+ Kernel.test(?d, @dir).should == true
+ end
+
+ platform_is_not :windows do
+ it "returns true when passed ?l if the argument is a symlink" do
+ link = tmp("file_symlink.lnk")
+ File.symlink(@file, link)
+ begin
+ Kernel.test(?l, link).should be_true
+ ensure
+ rm_r link
+ end
+ end
+ end
+
+ it "returns true when passed ?r if the argument is readable by the effective uid" do
+ Kernel.test(?r, @file).should be_true
+ end
+
+ it "returns true when passed ?R if the argument is readable by the real uid" do
+ Kernel.test(?R, @file).should be_true
+ end
+
+ it "returns true when passed ?w if the argument is readable by the effective uid" do
+ Kernel.test(?w, @file).should be_true
+ end
+
+ it "returns true when passed ?W if the argument is readable by the real uid" do
+ Kernel.test(?W, @file).should be_true
+ end
+
+ context "time commands" do
+ before :each do
+ @tmp_file = File.new(tmp("file.kernel.test"), "w")
+ end
+
+ after :each do
+ @tmp_file.close
+ rm_r @tmp_file
+ end
+
+ it "returns the last access time for the provided file when passed ?A" do
+ Kernel.test(?A, @tmp_file).should == @tmp_file.atime
+ end
+
+ it "returns the time at which the file was created when passed ?C" do
+ Kernel.test(?C, @tmp_file).should == @tmp_file.ctime
+ end
+
+ it "returns the time at which the file was modified when passed ?M" do
+ Kernel.test(?M, @tmp_file).should == @tmp_file.mtime
+ end
+ end
+
+ it "calls #to_path on second argument when passed ?f and a filename" do
+ p = mock('path')
+ p.should_receive(:to_path).and_return @file
+ Kernel.test(?f, p)
+ end
+
+ it "calls #to_path on second argument when passed ?e and a filename" do
+ p = mock('path')
+ p.should_receive(:to_path).and_return @file
+ Kernel.test(?e, p)
+ end
+
+ it "calls #to_path on second argument when passed ?d and a directory" do
+ p = mock('path')
+ p.should_receive(:to_path).and_return @dir
+ Kernel.test(?d, p)
+ end
+end
+
+describe "Kernel.test" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/throw_spec.rb b/spec/rubyspec/core/kernel/throw_spec.rb
new file mode 100644
index 0000000000..3f8d272d6d
--- /dev/null
+++ b/spec/rubyspec/core/kernel/throw_spec.rb
@@ -0,0 +1,80 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel.throw" do
+ it "transfers control to the end of the active catch block waiting for symbol" do
+ catch(:blah) do
+ :value
+ throw :blah
+ fail("throw didn't transfer the control")
+ end.should be_nil
+ end
+
+ it "transfers control to the innermost catch block waiting for the same sympol" do
+ one = two = three = 0
+ catch :duplicate do
+ catch :duplicate do
+ catch :duplicate do
+ one = 1
+ throw :duplicate
+ end
+ two = 2
+ throw :duplicate
+ end
+ three = 3
+ throw :duplicate
+ end
+ [one, two, three].should == [1, 2, 3]
+ end
+
+ it "sets the return value of the catch block to nil by default" do
+ res = catch :blah do
+ throw :blah
+ end
+ res.should == nil
+ end
+
+ it "sets the return value of the catch block to a value specified as second parameter" do
+ res = catch :blah do
+ throw :blah, :return_value
+ end
+ res.should == :return_value
+ end
+
+ it "raises an ArgumentError if there is no catch block for the symbol" do
+ lambda { throw :blah }.should raise_error(ArgumentError)
+ end
+
+ it "raises an UncaughtThrowError if there is no catch block for the symbol" do
+ lambda { throw :blah }.should raise_error(UncaughtThrowError)
+ end
+
+ it "raises ArgumentError if 3 or more arguments provided" do
+ lambda {
+ catch :blah do
+ throw :blah, :return_value, 2
+ end
+ }.should raise_error(ArgumentError)
+
+ lambda {
+ catch :blah do
+ throw :blah, :return_value, 2, 3, 4, 5
+ end
+ }.should raise_error(ArgumentError)
+ end
+
+ it "can throw an object" do
+ lambda {
+ obj = Object.new
+ catch obj do
+ throw obj
+ end
+ }.should_not raise_error(NameError)
+ end
+end
+
+describe "Kernel#throw" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:throw)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/to_enum_spec.rb b/spec/rubyspec/core/kernel/to_enum_spec.rb
new file mode 100644
index 0000000000..9fb228f318
--- /dev/null
+++ b/spec/rubyspec/core/kernel/to_enum_spec.rb
@@ -0,0 +1,5 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Kernel#to_enum" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/to_s_spec.rb b/spec/rubyspec/core/kernel/to_s_spec.rb
new file mode 100644
index 0000000000..c6fcca54a2
--- /dev/null
+++ b/spec/rubyspec/core/kernel/to_s_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#to_s" do
+ it "returns a String containing the name of self's class" do
+ Object.new.to_s.should =~ /Object/
+ end
+
+ it "returns a tainted result if self is tainted" do
+ Object.new.taint.to_s.tainted?.should be_true
+ end
+
+ it "returns an untrusted result if self is untrusted" do
+ Object.new.untrust.to_s.untrusted?.should be_true
+ end
+end
diff --git a/spec/rubyspec/core/kernel/trace_var_spec.rb b/spec/rubyspec/core/kernel/trace_var_spec.rb
new file mode 100644
index 0000000000..07e02feb72
--- /dev/null
+++ b/spec/rubyspec/core/kernel/trace_var_spec.rb
@@ -0,0 +1,54 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#trace_var" do
+ before :each do
+ $Kernel_trace_var_global = nil
+ end
+
+ after :each do
+ untrace_var :$Kernel_trace_var_global
+
+ $Kernel_trace_var_global = nil
+ $Kernel_trace_var_extra = nil
+ end
+
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:trace_var)
+ end
+
+ it "hooks assignments to a global variable" do
+ captured = nil
+
+ trace_var :$Kernel_trace_var_global do |value|
+ captured = value
+ end
+
+ $Kernel_trace_var_global = 'foo'
+ captured.should == 'foo'
+ end
+
+ it "accepts a proc argument instead of a block" do
+ captured = nil
+
+ trace_var :$Kernel_trace_var_global, proc {|value| captured = value}
+
+ $Kernel_trace_var_global = 'foo'
+ captured.should == 'foo'
+ end
+
+ # String arguments should be evaluated in the context of the caller.
+ it "accepts a String argument instead of a Proc or block" do
+ trace_var :$Kernel_trace_var_global, '$Kernel_trace_var_extra = true'
+
+ $Kernel_trace_var_global = 'foo'
+
+ $Kernel_trace_var_extra.should == true
+ end
+
+ it "raises ArgumentError if no block or proc is provided" do
+ lambda do
+ trace_var :$Kernel_trace_var_global
+ end.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/trap_spec.rb b/spec/rubyspec/core/kernel/trap_spec.rb
new file mode 100644
index 0000000000..98f386dc85
--- /dev/null
+++ b/spec/rubyspec/core/kernel/trap_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#trap" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:trap)
+ end
+end
+
+describe "Kernel.trap" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/trust_spec.rb b/spec/rubyspec/core/kernel/trust_spec.rb
new file mode 100644
index 0000000000..a9fda5c5c6
--- /dev/null
+++ b/spec/rubyspec/core/kernel/trust_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#trust" do
+ it "returns self" do
+ o = Object.new
+ o.trust.should equal(o)
+ end
+
+ it "clears the untrusted bit" do
+ o = Object.new.untrust
+ o.trust
+ o.untrusted?.should == false
+ end
+
+ it "raises RuntimeError on an untrusted, frozen object" do
+ o = Object.new.untrust.freeze
+ lambda { o.trust }.should raise_error(RuntimeError)
+ end
+
+ it "does not raise an error on a trusted, frozen object" do
+ o = Object.new.freeze
+ o.trust.should equal(o)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/untaint_spec.rb b/spec/rubyspec/core/kernel/untaint_spec.rb
new file mode 100644
index 0000000000..5abe5d63fc
--- /dev/null
+++ b/spec/rubyspec/core/kernel/untaint_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#untaint" do
+ it "returns self" do
+ o = Object.new
+ o.untaint.should equal(o)
+ end
+
+ it "clears the tainted bit" do
+ o = Object.new.taint
+ o.untaint
+ o.tainted?.should == false
+ end
+
+ it "raises RuntimeError on a tainted, frozen object" do
+ o = Object.new.taint.freeze
+ lambda { o.untaint }.should raise_error(RuntimeError)
+ end
+
+ it "does not raise an error on an untainted, frozen object" do
+ o = Object.new.freeze
+ o.untaint.should equal(o)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/untrace_var_spec.rb b/spec/rubyspec/core/kernel/untrace_var_spec.rb
new file mode 100644
index 0000000000..3af1348ffd
--- /dev/null
+++ b/spec/rubyspec/core/kernel/untrace_var_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#untrace_var" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:untrace_var)
+ end
+end
+
+describe "Kernel.untrace_var" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/rubyspec/core/kernel/untrust_spec.rb b/spec/rubyspec/core/kernel/untrust_spec.rb
new file mode 100644
index 0000000000..280a465807
--- /dev/null
+++ b/spec/rubyspec/core/kernel/untrust_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#untrust" do
+ it "returns self" do
+ o = Object.new
+ o.untrust.should equal(o)
+ end
+
+ it "sets the untrusted bit" do
+ o = Object.new
+ o.untrust
+ o.untrusted?.should == true
+ end
+
+ it "raises RuntimeError on a trusted, frozen object" do
+ o = Object.new.freeze
+ lambda { o.untrust }.should raise_error(RuntimeError)
+ end
+
+ it "does not raise an error on an untrusted, frozen object" do
+ o = Object.new.untrust.freeze
+ o.untrust.should equal(o)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/untrusted_spec.rb b/spec/rubyspec/core/kernel/untrusted_spec.rb
new file mode 100644
index 0000000000..43c4c0aa18
--- /dev/null
+++ b/spec/rubyspec/core/kernel/untrusted_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#untrusted?" do
+ it "returns the untrusted status of an object" do
+ o = mock('o')
+ o.untrusted?.should == false
+ o.untrust
+ o.untrusted?.should == true
+ end
+
+ it "has no effect on immediate values" do
+ a = nil
+ b = true
+ c = false
+ a.untrust
+ b.untrust
+ c.untrust
+ a.untrusted?.should == false
+ b.untrusted?.should == false
+ c.untrusted?.should == false
+ end
+
+ it "has effect on immediate values" do
+ d = 1
+ lambda { d.untrust }.should_not raise_error(RuntimeError)
+ end
+end
diff --git a/spec/rubyspec/core/kernel/warn_spec.rb b/spec/rubyspec/core/kernel/warn_spec.rb
new file mode 100644
index 0000000000..c44116dc21
--- /dev/null
+++ b/spec/rubyspec/core/kernel/warn_spec.rb
@@ -0,0 +1,79 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Kernel#warn" do
+ before :each do
+ @before_verbose = $VERBOSE
+ @before_separator = $/
+ end
+
+ after :each do
+ $VERBOSE = @before_verbose
+ $/ = @before_separator
+ end
+
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:warn)
+ end
+
+ it "requires multiple arguments" do
+ Kernel.method(:warn).arity.should < 0
+ end
+
+ it "does not append line-end if last character is line-end" do
+ lambda {
+ $VERBOSE = true
+ warn("this is some simple text with line-end\n")
+ }.should output(nil, "this is some simple text with line-end\n")
+ end
+
+ it "calls #write on $stderr if $VERBOSE is true" do
+ lambda {
+ $VERBOSE = true
+ warn("this is some simple text")
+ }.should output(nil, "this is some simple text\n")
+ end
+
+ it "calls #write on $stderr if $VERBOSE is false" do
+ lambda {
+ $VERBOSE = false
+ warn("this is some simple text")
+ }.should output(nil, "this is some simple text\n")
+ end
+
+ it "does not call #write on $stderr if $VERBOSE is nil" do
+ lambda {
+ $VERBOSE = nil
+ warn("this is some simple text")
+ }.should output(nil, "")
+ end
+
+ it "writes each argument on a line when passed multiple arguments" do
+ lambda {
+ $VERBOSE = true
+ warn("line 1", "line 2")
+ }.should output(nil, "line 1\nline 2\n")
+ end
+
+ it "writes each array element on a line when passes an array" do
+ lambda {
+ $VERBOSE = true
+ warn(["line 1", "line 2"])
+ }.should output(nil, "line 1\nline 2\n")
+ end
+
+ it "does not write strings when passed no arguments" do
+ lambda {
+ $VERBOSE = true
+ warn
+ }.should output("", "")
+ end
+
+ it "writes the default record separator and NOT $/ to $stderr after the warning message" do
+ lambda {
+ $VERBOSE = true
+ $/ = 'rs'
+ warn("")
+ }.should output(nil, /\n/)
+ end
+end