require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') include Fathom describe PlausibleRange do before do @d = {:upper_bound => 10, :lower_bound => 1} @pr = PlausibleRange.new(@d) end it "should require an upper and lower bound" do lambda{PlausibleRange.new}.should raise_error(/upper/) lambda{PlausibleRange.new(:upper_bound => 10)}.should raise_error(/lower/) lambda{PlausibleRange.new(:upper_bound => 10, :lower_bound => 1)}.should_not raise_error end it "should expose the upper bound and lower bound" do @pr.upper_bound.should eql(10) @pr.lower_bound.should eql(1) end it "should use min or max instead of lower_bound or upper_bound" do pr = PlausibleRange.new(:min => 1, :max => 10) pr.min.should eql(1) pr.max.should eql(10) pr.lower_bound.should eql(1) pr.upper_bound.should eql(10) end it "should allow an optional hard_lower_bound" do pr = PlausibleRange.new(@d.merge(:hard_lower_bound => 0)) pr.hard_lower_bound.should eql(0) end it "should set the lower_bound to the hard_lower_bound if the hard_lower_bound is greater than the lower_bound" do pr = PlausibleRange.new(:lower_bound => 2, :hard_lower_bound => 3, :upper_bound => 4) pr.lower_bound.should eql(3) end it "should allow an optional hard_upper_bound" do pr = PlausibleRange.new(@d.merge(:hard_upper_bound => 20)) pr.hard_upper_bound.should eql(20) end it "should set the upper_bound to the hard_upper_bound if the hard_upper_bound is less than the upper_bound" do pr = PlausibleRange.new(:lower_bound => 2, :hard_upper_bound => 3, :upper_bound => 4) pr.upper_bound.should eql(3) end it "should have a default confidence interval of 90%" do @pr.confidence_interval.should eql(0.9) end it "should be able to instantiate with confidence_interval" do pr = PlausibleRange.new(@d.merge(:confidence_interval => 0.8)) pr.confidence_interval.should eql(0.8) end it "should be able to use ci instead of confidence_interval" do pr = PlausibleRange.new(@d.merge(:ci => 0.8)) pr.ci.should eql(0.8) pr.confidence_interval.should eql(0.8) end it "should be able to calculate the midpoint" do @pr.midpoint.should eql(5.5) end it "should be able to calculate the standard deviation" do @pr.standard_deviation.should be_close( 2.7358, 0.0001) end it "should be able to use std instead of standard_deviation" do @pr.std.should eql(@pr.standard_deviation) end it "should be able to produce a random value from within the distribution" do @pr.should be_respond_to(:rand) @pr.rand.should be_a(Float) end it "should be able to produce an array of random values" do @pr.array_of_random_values.should be_an(Array) @pr.array_of_random_values.length.should eql(10) @pr.array_of_random_values(13).length.should eql(13) end it "should alias array_of_random_values with to_a" do @pr.to_a.should be_an(Array) @pr.to_a.length.should eql(10) @pr.to_a(13).length.should eql(13) end it "should be able to produce a vector of random values" do @pr.vector_of_random_values.should be_a(GSL::Vector) @pr.vector_of_random_values.length.should eql(10) @pr.vector_of_random_values(12).length.should eql(12) end it "should alias vector_of_random_values with to_v" do @pr.to_v.should be_a(GSL::Vector) @pr.to_v.length.should eql(10) @pr.to_v(12).length.should eql(12) end it "should record the name, if one is provided" do pr = PlausibleRange.new(@d.merge(:name => 'pr1')) pr.name.should eql('pr1') end it "should record the description, if one is provided" do pr = PlausibleRange.new(@d.merge(:description => 'some description')) pr.description.should eql('some description') end it "should have no problems with a range with matching lower and upper bounds" do pr = PlausibleRange.new(:min => 1, :max => 1) pr.rand.should eql(1.0) pr.midpoint.should eql(1.0) pr.std.should eql(0.0) end it "should have a name_sym method" do pr = PlausibleRange.new(:min => 1, :max => 2, :name => "Demo Node") pr.name_sym.should eql(:demo_node) end it "should not exceed the lower bound if it is set", :slow => true do pr = PlausibleRange.new(:max => 100, :hard_lower_bound => 0) 1_000.times do (pr.rand >= 0).should eql(true) end end it "should not exceed the upper bound if it is set", :slow => true do pr = PlausibleRange.new(:min => 0, :hard_upper_bound => 100) 1_000.times do (pr.rand <= 100).should eql(true) end end it "should not exceed the lower bound or upper bound if both are set", :slow => true do pr = PlausibleRange.new(:hard_upper_bound => 100, :hard_lower_bound => 0) 1_000.times do r = pr.rand (r >= 0 and r <= 100).should eql(true) end end end