diff options
Diffstat (limited to 'spec/ruby/core/random')
-rw-r--r-- | spec/ruby/core/random/bytes_spec.rb | 39 | ||||
-rw-r--r-- | spec/ruby/core/random/default_spec.rb | 7 | ||||
-rw-r--r-- | spec/ruby/core/random/equal_value_spec.rb | 37 | ||||
-rw-r--r-- | spec/ruby/core/random/new_seed_spec.rb | 24 | ||||
-rw-r--r-- | spec/ruby/core/random/new_spec.rb | 37 | ||||
-rw-r--r-- | spec/ruby/core/random/rand_spec.rb | 216 | ||||
-rw-r--r-- | spec/ruby/core/random/raw_seed_spec.rb | 9 | ||||
-rw-r--r-- | spec/ruby/core/random/seed_spec.rb | 29 | ||||
-rw-r--r-- | spec/ruby/core/random/shared/urandom.rb | 23 | ||||
-rw-r--r-- | spec/ruby/core/random/srand_spec.rb | 39 | ||||
-rw-r--r-- | spec/ruby/core/random/urandom_spec.rb | 9 |
11 files changed, 469 insertions, 0 deletions
diff --git a/spec/ruby/core/random/bytes_spec.rb b/spec/ruby/core/random/bytes_spec.rb new file mode 100644 index 0000000000..2434a4e72e --- /dev/null +++ b/spec/ruby/core/random/bytes_spec.rb @@ -0,0 +1,39 @@ +# -*- encoding: binary -*- +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Random#bytes" do + it "returns a String" do + Random.new.bytes(1).should be_an_instance_of(String) + end + + it "returns a String of the length given as argument" do + Random.new.bytes(15).length.should == 15 + end + + it "returns an ASCII-8BIT String" do + Random.new.bytes(15).encoding.should == Encoding::ASCII_8BIT + end + + it "returns the same output for a given seed" do + Random.new(33).bytes(2).should == Random.new(33).bytes(2) + end + + # Should double check this is official spec + it "returns the same numeric output for a given seed accross all implementations and platforms" do + rnd = Random.new(33) + rnd.bytes(2).should == "\x14\\" + rnd.bytes(1000) # skip some + rnd.bytes(2).should == "\xA1p" + end + + it "returns the same numeric output for a given huge seed accross all implementations and platforms" do + rnd = Random.new(bignum_value ** 4) + rnd.bytes(2).should == "_\x91" + rnd.bytes(1000) # skip some + rnd.bytes(2).should == "\x17\x12" + end + + it "returns a random binary String" do + Random.new.bytes(12).should_not == Random.new.bytes(12) + end +end diff --git a/spec/ruby/core/random/default_spec.rb b/spec/ruby/core/random/default_spec.rb new file mode 100644 index 0000000000..51a76c01ce --- /dev/null +++ b/spec/ruby/core/random/default_spec.rb @@ -0,0 +1,7 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Random::DEFAULT" do + it "returns a Random instance" do + Random::DEFAULT.should be_an_instance_of(Random) + end +end diff --git a/spec/ruby/core/random/equal_value_spec.rb b/spec/ruby/core/random/equal_value_spec.rb new file mode 100644 index 0000000000..738f549f1d --- /dev/null +++ b/spec/ruby/core/random/equal_value_spec.rb @@ -0,0 +1,37 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Random#==" do + it "returns true if the two objects have the same state" do + a = Random.new(42) + b = Random.new(42) + a.send(:state).should == b.send(:state) + a.should == b + end + + it "returns false if the two objects have different state" do + a = Random.new + b = Random.new + a.send(:state).should_not == b.send(:state) + a.should_not == b + end + + it "returns true if the two objects have the same seed" do + a = Random.new(42) + b = Random.new(42.5) + a.seed.should == b.seed + a.should == b + end + + it "returns false if the two objects have a different seed" do + a = Random.new(42) + b = Random.new(41) + a.seed.should_not == b.seed + a.should_not == b + end + + it "returns false if the other object is not a Random" do + a = Random.new(42) + a.should_not == 42 + a.should_not == [a] + end +end diff --git a/spec/ruby/core/random/new_seed_spec.rb b/spec/ruby/core/random/new_seed_spec.rb new file mode 100644 index 0000000000..a8efaee2b1 --- /dev/null +++ b/spec/ruby/core/random/new_seed_spec.rb @@ -0,0 +1,24 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Random.new_seed" do + it "returns a Bignum" do + Random.new_seed.should be_an_instance_of(Bignum) + end + + it "returns an arbitrary seed value each time" do + bigs = 200.times.map { Random.new_seed } + bigs.uniq.size.should == 200 + end + + it "is not affected by Kernel#srand" do + begin + srand 25 + a = Random.new_seed + srand 25 + b = Random.new_seed + a.should_not == b + ensure + srand Random.new_seed + end + end +end diff --git a/spec/ruby/core/random/new_spec.rb b/spec/ruby/core/random/new_spec.rb new file mode 100644 index 0000000000..8160f44d79 --- /dev/null +++ b/spec/ruby/core/random/new_spec.rb @@ -0,0 +1,37 @@ +describe "Random.new" do + it "returns a new instance of Random" do + Random.new.should be_an_instance_of(Random) + end + + it "uses a random seed value if none is supplied" do + Random.new.seed.should be_an_instance_of(Bignum) + end + + it "returns Random instances initialized with different seeds" do + first = Random.new + second = Random.new + (0..20).map { first.rand } .should_not == (0..20).map { second.rand } + end + + it "accepts an Integer seed value as an argument" do + Random.new(2).seed.should == 2 + end + + it "accepts (and truncates) a Float seed value as an argument" do + Random.new(3.4).seed.should == 3 + end + + it "accepts (and converts to Integer) a Rational seed value as an argument" do + Random.new(Rational(20,2)).seed.should == 10 + end + + it "accepts (and converts to Integer) a Complex (without imaginary part) seed value as an argument" do + Random.new(Complex(20)).seed.should == 20 + end + + it "raises a RangeError if passed a Complex (with imaginary part) seed value as an argument" do + lambda do + Random.new(Complex(20,2)) + end.should raise_error(RangeError) + end +end diff --git a/spec/ruby/core/random/rand_spec.rb b/spec/ruby/core/random/rand_spec.rb new file mode 100644 index 0000000000..e0cb133abd --- /dev/null +++ b/spec/ruby/core/random/rand_spec.rb @@ -0,0 +1,216 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Random.rand" do + it "returns a Float if no max argument is passed" do + Random.rand.should be_kind_of(Float) + end + + it "returns a Float >= 0 if no max argument is passed" do + floats = 200.times.map { Random.rand } + floats.min.should >= 0 + end + + it "returns a Float < 1 if no max argument is passed" do + floats = 200.times.map { Random.rand } + floats.max.should < 1 + end + + it "returns the same sequence for a given seed if no max argument is passed" do + Random.srand 33 + floats_a = 20.times.map { Random.rand } + Random.srand 33 + floats_b = 20.times.map { Random.rand } + floats_a.should == floats_b + end + + it "returns an Integer if an Integer argument is passed" do + Random.rand(20).should be_kind_of(Integer) + end + + it "returns an Integer >= 0 if an Integer argument is passed" do + ints = 200.times.map { Random.rand(34) } + ints.min.should >= 0 + end + + it "returns an Integer < the max argument if an Integer argument is passed" do + ints = 200.times.map { Random.rand(55) } + ints.max.should < 55 + end + + it "returns the same sequence for a given seed if an Integer argument is passed" do + Random.srand 33 + floats_a = 20.times.map { Random.rand(90) } + Random.srand 33 + floats_b = 20.times.map { Random.rand(90) } + floats_a.should == floats_b + end + + it "coerces arguments to Integers with #to_int" do + obj = mock_numeric('int') + obj.should_receive(:to_int).and_return(99) + Random.rand(obj).should be_kind_of(Integer) + end +end + +describe "Random#rand with Fixnum" do + it "returns an Integer" do + Random.new.rand(20).should be_an_instance_of(Fixnum) + end + + it "returns a Fixnum greater than or equal to 0" do + prng = Random.new + ints = 20.times.map { prng.rand(5) } + ints.min.should >= 0 + end + + it "returns a Fixnum less than the argument" do + prng = Random.new + ints = 20.times.map { prng.rand(5) } + ints.max.should <= 4 + end + + it "returns the same sequence for a given seed" do + prng = Random.new 33 + a = 20.times.map { prng.rand(90) } + prng = Random.new 33 + b = 20.times.map { prng.rand(90) } + a.should == b + end + + it "eventually returns all possible values" do + prng = Random.new 33 + 100.times.map{ prng.rand(10) }.uniq.sort.should == (0...10).to_a + end + + it "raises an ArgumentError when the argument is 0" do + lambda do + Random.new.rand(0) + end.should raise_error(ArgumentError) + end + + it "raises an ArgumentError when the argument is negative" do + lambda do + Random.new.rand(-12) + end.should raise_error(ArgumentError) + end +end + +describe "Random#rand with Bignum" do + it "typically returns a Bignum" do + rnd = Random.new(1) + 10.times.map{ rnd.rand(bignum_value*2) }.max.should be_an_instance_of(Bignum) + end + + it "returns a Bignum greater than or equal to 0" do + prng = Random.new + bigs = 20.times.map { prng.rand(bignum_value) } + bigs.min.should >= 0 + end + + it "returns a Bignum less than the argument" do + prng = Random.new + bigs = 20.times.map { prng.rand(bignum_value) } + bigs.max.should < bignum_value + end + + it "returns the same sequence for a given seed" do + prng = Random.new 33 + a = 20.times.map { prng.rand(bignum_value) } + prng = Random.new 33 + b = 20.times.map { prng.rand(bignum_value) } + a.should == b + end + + it "raises an ArgumentError when the argument is negative" do + lambda do + Random.new.rand(-bignum_value) + end.should raise_error(ArgumentError) + end +end + +describe "Random#rand with Float" do + it "returns a Float" do + Random.new.rand(20.43).should be_an_instance_of(Float) + end + + it "returns a Float greater than or equal to 0.0" do + prng = Random.new + floats = 20.times.map { prng.rand(5.2) } + floats.min.should >= 0.0 + end + + it "returns a Float less than the argument" do + prng = Random.new + floats = 20.times.map { prng.rand(4.30) } + floats.max.should < 4.30 + end + + it "returns the same sequence for a given seed" do + prng = Random.new 33 + a = 20.times.map { prng.rand(89.2928) } + prng = Random.new 33 + b = 20.times.map { prng.rand(89.2928) } + a.should == b + end + + it "raises an ArgumentError when the argument is negative" do + lambda do + Random.new.rand(-1.234567) + end.should raise_error(ArgumentError) + end +end + +describe "Random#rand with Range" do + it "returns an element from the Range" do + Random.new.rand(20..43).should be_an_instance_of(Fixnum) + end + + it "returns an object that is a member of the Range" do + prng = Random.new + r = 20..30 + 20.times { r.member?(prng.rand(r)).should be_true } + end + + it "works with inclusive ranges" do + prng = Random.new 33 + r = 3..5 + 40.times.map { prng.rand(r) }.uniq.sort.should == [3,4,5] + end + + it "works with exclusive ranges" do + prng = Random.new 33 + r = 3...5 + 20.times.map { prng.rand(r) }.uniq.sort.should == [3,4] + end + + it "returns the same sequence for a given seed" do + prng = Random.new 33 + a = 20.times.map { prng.rand(76890.028..800000.00) } + prng = Random.new 33 + b = 20.times.map { prng.rand(76890.028..800000.00) } + a.should == b + end + + it "eventually returns all possible values" do + prng = Random.new 33 + 100.times.map{ prng.rand(10..20) }.uniq.sort.should == (10..20).to_a + 100.times.map{ prng.rand(10...20) }.uniq.sort.should == (10...20).to_a + end + + it "considers Integers as Floats if one end point is a float" do + Random.new(42).rand(0.0..1).should be_kind_of(Float) + Random.new(42).rand(0..1.0).should be_kind_of(Float) + end + + it "raises an ArgumentError when the startpoint lacks #+ and #- methods" do + lambda do + Random.new.rand(Object.new..67) + end.should raise_error(ArgumentError) + end + + it "raises an ArgumentError when the endpoint lacks #+ and #- methods" do + lambda do + Random.new.rand(68..Object.new) + end.should raise_error(ArgumentError) + end +end diff --git a/spec/ruby/core/random/raw_seed_spec.rb b/spec/ruby/core/random/raw_seed_spec.rb new file mode 100644 index 0000000000..881cceada9 --- /dev/null +++ b/spec/ruby/core/random/raw_seed_spec.rb @@ -0,0 +1,9 @@ +# -*- encoding: binary -*- +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../shared/urandom', __FILE__) + +ruby_version_is "2.5" do + describe "Random.urandom" do + it_behaves_like :random_urandom, :urandom + end +end diff --git a/spec/ruby/core/random/seed_spec.rb b/spec/ruby/core/random/seed_spec.rb new file mode 100644 index 0000000000..5acb068efe --- /dev/null +++ b/spec/ruby/core/random/seed_spec.rb @@ -0,0 +1,29 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Random#seed" do + it "returns an Integer" do + Random.new.seed.should be_kind_of(Integer) + end + + it "returns an arbitrary seed if the constructor was called without arguments" do + Random.new.seed.should_not == Random.new.seed + end + + it "returns the same generated seed when repeatedly called on the same object" do + prng = Random.new + prng.seed.should == prng.seed + end + + it "returns the seed given in the constructor" do + prng = Random.new(36788) + prng.seed.should == prng.seed + prng.seed.should == 36788 + end + + it "returns the given seed coerced with #to_int" do + obj = mock_numeric('int') + obj.should_receive(:to_int).and_return(34) + prng = Random.new(obj) + prng.seed.should == 34 + end +end diff --git a/spec/ruby/core/random/shared/urandom.rb b/spec/ruby/core/random/shared/urandom.rb new file mode 100644 index 0000000000..f50d30c9de --- /dev/null +++ b/spec/ruby/core/random/shared/urandom.rb @@ -0,0 +1,23 @@ +describe :random_urandom, shared: true do + it "returns a String" do + Random.send(@method, 1).should be_an_instance_of(String) + end + + it "returns a String of the length given as argument" do + Random.send(@method, 15).length.should == 15 + end + + it "raises an ArgumentError on a negative size" do + lambda { + Random.send(@method, -1) + }.should raise_error(ArgumentError) + end + + it "returns an ASCII-8BIT String" do + Random.send(@method, 15).encoding.should == Encoding::ASCII_8BIT + end + + it "returns a random binary String" do + Random.send(@method, 12).should_not == Random.send(@method, 12) + end +end diff --git a/spec/ruby/core/random/srand_spec.rb b/spec/ruby/core/random/srand_spec.rb new file mode 100644 index 0000000000..8ce863f5a9 --- /dev/null +++ b/spec/ruby/core/random/srand_spec.rb @@ -0,0 +1,39 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Random.srand" do + it "returns an arbitrary seed if .srand wasn't called previously with an argument and no argument is supplied this time" do + Random.srand # Reset to random seed in case .srand was called previously + Random.srand.should_not == Random.srand + end + + it "returns the previous argument to .srand if one was given and no argument is supplied" do + Random.srand 34 + Random.srand.should == 34 + end + + it "returns an arbitrary seed if .srand wasn't called previously with an argument and 0 is supplied this time" do + Random.srand # Reset to random seed in case .srand was called previously + Random.srand(0).should_not == Random.srand(0) + end + + it "returns the previous argument to .srand if one was given and 0 is supplied" do + Random.srand 34 + Random.srand(0).should == 34 + end + + it "seeds Random.rand such that its return value is deterministic" do + Random.srand 176542 + a = 20.times.map { Random.rand } + Random.srand 176542 + b = 20.times.map { Random.rand } + a.should == b + end + + it "seeds Kernel.rand such that its return value is deterministic" do + Random.srand 176542 + a = 20.times.map { Kernel.rand } + Random.srand 176542 + b = 20.times.map { Kernel.rand } + a.should == b + end +end diff --git a/spec/ruby/core/random/urandom_spec.rb b/spec/ruby/core/random/urandom_spec.rb new file mode 100644 index 0000000000..1cc0103e35 --- /dev/null +++ b/spec/ruby/core/random/urandom_spec.rb @@ -0,0 +1,9 @@ +# -*- encoding: binary -*- +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../shared/urandom', __FILE__) + +ruby_version_is "2.3"..."2.5" do + describe "Random.raw_seed" do + it_behaves_like :random_urandom, :raw_seed + end +end |