From 8a87d8a6c2c6dfb423bcaf61c750010d80993b16 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 22 Jul 2008 10:26:44 -0500 Subject: Improved Memoizable test coverage and added support for multiple arguments --- activesupport/test/memoizable_test.rb | 166 ++++++++++++++++++++++++++-------- 1 file changed, 127 insertions(+), 39 deletions(-) (limited to 'activesupport/test') diff --git a/activesupport/test/memoizable_test.rb b/activesupport/test/memoizable_test.rb index 79769631ad..cd84dcda53 100644 --- a/activesupport/test/memoizable_test.rb +++ b/activesupport/test/memoizable_test.rb @@ -5,86 +5,174 @@ uses_mocha 'Memoizable' do class Person extend ActiveSupport::Memoizable - def name - fetch_name_from_floppy + attr_reader :name_calls, :age_calls + def initialize + @name_calls = 0 + @age_calls = 0 end - memoize :name + def name + @name_calls += 1 + "Josh" + end def age + @age_calls += 1 nil end - def counter - @counter ||= 0 - @counter += 1 + memoize :name, :age + end + + class Company + attr_reader :name_calls + def initialize + @name_calls = 0 end - memoize :age, :counter + def name + @name_calls += 1 + "37signals" + end + end + + module Rates + extend ActiveSupport::Memoizable - private - def fetch_name_from_floppy - "Josh" + attr_reader :sales_tax_calls + def sales_tax(price) + @sales_tax_calls ||= 0 + @sales_tax_calls += 1 + price * 0.1025 + end + memoize :sales_tax + end + + class Calculator + extend ActiveSupport::Memoizable + include Rates + + attr_reader :fib_calls + def initialize + @fib_calls = 0 + end + + def fib(n) + @fib_calls += 1 + + if n == 0 || n == 1 + n + else + fib(n - 1) + fib(n - 2) end + end + memoize :fib + + def counter + @count ||= 0 + @count += 1 + end + memoize :counter end def setup @person = Person.new + @calculator = Calculator.new end def test_memoization assert_equal "Josh", @person.name + assert_equal 1, @person.name_calls - @person.expects(:fetch_name_from_floppy).never - 2.times { assert_equal "Josh", @person.name } + 3.times { assert_equal "Josh", @person.name } + assert_equal 1, @person.name_calls + end + + def test_memoization_with_nil_value + assert_equal nil, @person.age + assert_equal 1, @person.age_calls + + 3.times { assert_equal nil, @person.age } + assert_equal 1, @person.age_calls end def test_reloadable - counter = @person.counter - assert_equal 1, @person.counter - assert_equal 2, @person.counter(:reload) + counter = @calculator.counter + assert_equal 1, @calculator.counter + assert_equal 2, @calculator.counter(:reload) + assert_equal 2, @calculator.counter + assert_equal 3, @calculator.counter(true) + assert_equal 3, @calculator.counter end - def test_memoized_methods_are_frozen - assert_equal true, @person.name.frozen? + def test_memoization_cache_is_different_for_each_instance + assert_equal 1, @calculator.counter + assert_equal 2, @calculator.counter(:reload) + assert_equal 1, Calculator.new.counter + end + def test_memoized_is_not_affected_by_freeze @person.freeze assert_equal "Josh", @person.name - assert_equal true, @person.name.frozen? end - def test_memoization_frozen_with_nil_value - @person.freeze - assert_equal nil, @person.age + def test_memoization_with_args + assert_equal 55, @calculator.fib(10) + assert_equal 11, @calculator.fib_calls end - def test_double_memoization - assert_raise(RuntimeError) { Person.memoize :name } + def test_reloadable_with_args + assert_equal 55, @calculator.fib(10) + assert_equal 11, @calculator.fib_calls + assert_equal 55, @calculator.fib(10, :reload) + assert_equal 12, @calculator.fib_calls + assert_equal 55, @calculator.fib(10, true) + assert_equal 13, @calculator.fib_calls end - class Company - def name - lookup_name + def test_object_memoization + [Company.new, Company.new, Company.new].each do |company| + company.extend ActiveSupport::Memoizable + company.memoize :name + + assert_equal "37signals", company.name + assert_equal 1, company.name_calls + assert_equal "37signals", company.name + assert_equal 1, company.name_calls end + end - def lookup_name - "37signals" - end + def test_memoized_module_methods + assert_equal 1.025, @calculator.sales_tax(10) + assert_equal 1, @calculator.sales_tax_calls + assert_equal 1.025, @calculator.sales_tax(10) + assert_equal 1, @calculator.sales_tax_calls + assert_equal 2.5625, @calculator.sales_tax(25) + assert_equal 2, @calculator.sales_tax_calls end - def test_object_memoization + def test_object_memoized_module_methods company = Company.new - company.extend ActiveSupport::Memoizable - company.memoize :name + company.extend(Rates) + + assert_equal 1.025, company.sales_tax(10) + assert_equal 1, company.sales_tax_calls + assert_equal 1.025, company.sales_tax(10) + assert_equal 1, company.sales_tax_calls + assert_equal 2.5625, company.sales_tax(25) + assert_equal 2, company.sales_tax_calls + end - assert_equal "37signals", company.name - # Mocha doesn't play well with frozen objects - company.metaclass.instance_eval { define_method(:lookup_name) { b00m } } - assert_equal "37signals", company.name + def test_double_memoization + assert_raise(RuntimeError) { Person.memoize :name } + person = Person.new + person.extend ActiveSupport::Memoizable + assert_raise(RuntimeError) { person.memoize :name } - assert_equal true, company.name.frozen? - company.freeze - assert_equal true, company.name.frozen? + company = Company.new + company.extend ActiveSupport::Memoizable + company.memoize :name + assert_raise(RuntimeError) { company.memoize :name } end end end -- cgit v1.2.3