require_relative '../../spec_helper' require_relative 'fixtures/classes' describe "Kernel#rand" do it "is a private method" do Kernel.private_instance_methods(false).should.include?(:rand) end it "returns a float if no argument is passed" do rand.should.is_a?(Float) end it "returns an integer for an integer argument" do rand(77).should.is_a?(Integer) end it "returns an integer for a float argument greater than 1" do rand(1.3).should.is_a?(Integer) end it "returns a float for an argument between -1 and 1" do rand(-0.999).should.is_a?(Float) rand(-0.01).should.is_a?(Float) rand(0).should.is_a?(Float) rand(0.01).should.is_a?(Float) rand(0.999).should.is_a?(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.is_a?(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.is_a?(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.is_a?(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.is_a?(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.is_a?(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.is_a?(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.is_a?(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.is_a?(Float) (3.5..6.5).should.include?(x) end end end context "given an inclusive range between 0 and 1" do it "returns an Integer between the two Integers" do x = rand(0..1) x.should.is_a?(Integer) (0..1).should.include?(x) end it "returns a Float if at least one side is Float" do seed = 42 x1 = Random.new(seed).rand(0..1.0) x2 = Random.new(seed).rand(0.0..1.0) x3 = Random.new(seed).rand(0.0..1) x3.should.is_a?(Float) x1.should.eql?(x3) x2.should.eql?(x3) (0.0..1.0).should.include?(x3) end end context "given an exclusive range between 0 and 1" do it "returns zero as an Integer" do x = rand(0...1) x.should.is_a?(Integer) x.should.eql?(0) end it "returns a Float if at least one side is Float" do seed = 42 x1 = Random.new(seed).rand(0...1.0) x2 = Random.new(seed).rand(0.0...1.0) x3 = Random.new(seed).rand(0.0...1) x3.should.is_a?(Float) x1.should.eql?(x3) x2.should.eql?(x3) (0.0...1.0).should.include?(x3) end end it "returns a numeric for an range argument where max is < 1" do rand(0.25..0.75).should.is_a?(Numeric) end it "returns nil when range is backwards" do rand(1..0).should == 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 it "supports custom object types" do rand(KernelSpecs::CustomRangeInteger.new(1)..KernelSpecs::CustomRangeInteger.new(42)).should.instance_of?(KernelSpecs::CustomRangeInteger) rand(KernelSpecs::CustomRangeFloat.new(1.0)..KernelSpecs::CustomRangeFloat.new(42.0)).should.instance_of?(KernelSpecs::CustomRangeFloat) rand(Time.now..Time.now).should.instance_of?(Time) end it "is random on boot" do results = 2.times.map { out = ruby_exe('p rand', options: '--disable-gems') Float(out) } results.size.should == 2 # this is technically flaky, but very unlikely in a good distribution results[0].should_not == results[1] end end describe "Kernel.rand" do it "needs to be reviewed for spec completeness" end