Created
March 14, 2010 06:49
-
-
Save matthewd/331810 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 7b4f0646096edb78b4ca48ba028576fded3369d0 Mon Sep 17 00:00:00 2001 | |
From: Matthew Draper <matthew@trebex.net> | |
Date: Sun, 14 Mar 2010 15:28:39 +1030 | |
Subject: [PATCH] Improve & extend Kernel.{rand,srand} specs. | |
--- | |
spec/ruby/core/kernel/rand_spec.rb | 101 +++++++++++++++++++++++++++++++---- | |
spec/ruby/core/kernel/srand_spec.rb | 35 +++++++++++-- | |
2 files changed, 121 insertions(+), 15 deletions(-) | |
diff --git a/spec/ruby/core/kernel/rand_spec.rb b/spec/ruby/core/kernel/rand_spec.rb | |
index 581c11f..19b48d1 100644 | |
--- a/spec/ruby/core/kernel/rand_spec.rb | |
+++ b/spec/ruby/core/kernel/rand_spec.rb | |
@@ -5,34 +5,113 @@ describe "Kernel.rand" do | |
it "is a private method" do | |
Kernel.should have_private_instance_method(:rand) | |
end | |
- | |
- it "returns a random float less than 1 if no max argument is passed" do | |
- rand.kind_of?(Float).should == true | |
+ | |
+ 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 "can return a bignum when given a large enough limit" do | |
+ # Probability of random failure: | |
+ # 64-bit: 1 in 10**42 | |
+ # 32-bit: 1 in 10**139 | |
+ | |
+ values = [] | |
+ 10.times do | |
+ values << rand(0x12345678901234567890) | |
+ end | |
+ values.max.should be_kind_of(Bignum) | |
end | |
- it "returns a random int or bigint less than the argument for an integer argument" do | |
- rand(77).kind_of?(Integer).should == true | |
+ it "can return a large bignum when given a large enough limit" do | |
+ # Probability of random failure: 1 in 10**80 | |
+ | |
+ values = [] | |
+ 10.times do | |
+ values << rand(0x123456789012345678901234567890) | |
+ end | |
+ values.max.should > (0x123456789012345678901234567890 / 100_000_000) | |
end | |
- it "returns a random integer less than the argument casted to an int for a float argument greater than 1" do | |
- rand(1.3).kind_of?(Integer).should == true | |
+ it "can return a fixnum even when given a bignum limit" do | |
+ # Probability of random failure: 1 in 10**60 | |
+ | |
+ small_bignum = 1 | |
+ small_bignum *= 2 until small_bignum.is_a? Bignum | |
+ small_bignum *= 2 # for good measure | |
+ | |
+ values = [] | |
+ 200.times do | |
+ values << rand(small_bignum) | |
+ end | |
+ values.min.should be_kind_of(Fixnum) | |
+ values.max.should be_kind_of(Bignum) | |
end | |
- it "returns a random float less than 1 for float arguments less than 1" do | |
- rand(0.01).kind_of?(Float).should == true | |
+ it "produces a vaguely even distribution" do | |
+ # Like several other rand specs, this one is based on probabilities; | |
+ # with a sufficiently high quality RNG, this spec should fail | |
+ # occassionally. | |
+ | |
+ # Probability of random failure: 1 in 10**20 | |
+ | |
+ counts = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] | |
+ 5000.times do |i| | |
+ n = rand(10) | |
+ counts[n] += 1 | |
+ end | |
+ | |
+ # Under a perfect distribution (which obviously wouldn't be random), | |
+ # all values in 'counts' are 500. | |
+ # We ignore the highest and lowest value, then apply a +/-30% | |
+ # tolerance on the remaining 8 -- this is a trade-off between | |
+ # strictness, and likelihood of random failure. For comparison, a | |
+ # +/-20% tolerance would increase probability of random failure to | |
+ # about 1 in 10**10, and +/-10% would make the probability | |
+ # approximately 1 in 100. | |
+ | |
+ counts.sort! | |
+ counts[1].should > 350 | |
+ counts[-2].should < 650 | |
end | |
it "never returns a value greater or equal to 1.0 with no arguments" do | |
1000.times do | |
- (rand < 1.0).should == true | |
+ (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 | |
- (rand(100) < 100).should == true | |
+ (0...100).to_a.should include(rand(100)) | |
end | |
end | |
+ | |
+ it "calls to_i on its argument" do | |
+ l = mock('limit') | |
+ l.should_receive(:to_i).and_return 7 | |
+ | |
+ rand l | |
+ end | |
end | |
describe "Kernel#rand" do | |
diff --git a/spec/ruby/core/kernel/srand_spec.rb b/spec/ruby/core/kernel/srand_spec.rb | |
index dd4d288..33f99f5 100644 | |
--- a/spec/ruby/core/kernel/srand_spec.rb | |
+++ b/spec/ruby/core/kernel/srand_spec.rb | |
@@ -5,13 +5,13 @@ describe "Kernel.srand" do | |
it "is a private method" do | |
Kernel.should have_private_instance_method(:srand) | |
end | |
- | |
- it "srand should return the previous seed value" do | |
+ | |
+ it "returns the previous seed value" do | |
srand(10) | |
srand(20).should == 10 | |
end | |
- it "srand should seed the RNG correctly and repeatably" do | |
+ it "seeds the RNG correctly and repeatably" do | |
srand(10) | |
x = rand | |
srand(10) | |
@@ -23,9 +23,36 @@ describe "Kernel.srand" do | |
srand.should_not == 0 | |
end | |
- it "calls #to_i on number" do | |
+ 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 | |
-- | |
1.7.0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment