Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Tree: 2e947e6e92
Fetching contributors…

Cannot retrieve contributors at this time

332 lines (264 sloc) 7.325 kB
require 'test_helper'
require 'memoist'
class MemoistTest < Test::Unit::TestCase
class CallCounter
def initialize
@calls = {}
end
def call(method_name)
@calls[method_name] ||= 0
@calls[method_name] += 1
end
def count(method_name)
@calls[method_name] ||= 0
end
end
class Person
extend Memoist
def initialize
@counter = CallCounter.new
end
def name_calls
@counter.count(:name)
end
def student_name_calls
@counter.count(:student_name)
end
def name_query_calls
@counter.count(:name?)
end
def is_developer_calls
@counter.count(:is_developer?)
end
def age_calls
@counter.count(:age)
end
def name
@counter.call(:name)
"Josh"
end
def name?
@counter.call(:name?)
true
end
memoize :name?
def update(name)
"Joshua"
end
memoize :update
def age
@counter.call(:age)
nil
end
memoize :name, :age
protected
def memoize_protected_test
'protected'
end
memoize :memoize_protected_test
private
def is_developer?
@counter.call(:is_developer?)
"Yes"
end
memoize :is_developer?
end
class Student < Person
def name
@counter.call(:student_name)
"Student #{super}"
end
memoize :name, :identifier => :student
end
class Company
attr_reader :name_calls
def initialize
@name_calls = 0
end
def name
@name_calls += 1
"37signals"
end
end
module Rates
extend Memoist
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 Memoist
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 add_or_subtract(i, j, add)
if add
i + j
else
i - j
end
end
memoize :add_or_subtract
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
3.times { assert_equal "Josh", @person.name }
assert_equal 1, @person.name_calls
end
def test_memoization_with_punctuation
assert_equal true, @person.name?
assert_nothing_raised(NameError) do
@person.memoize_all
@person.unmemoize_all
end
end
def test_memoization_flush_with_punctuation
assert_equal true, @person.name?
@person.flush_cache(:name?)
3.times { assert_equal true, @person.name? }
assert_equal 2, @person.name_query_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
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_flush_cache
assert_equal 1, @calculator.counter
assert @calculator.instance_variable_get(:@_memoized_counter).any?
@calculator.flush_cache(:counter)
assert @calculator.instance_variable_get(:@_memoized_counter).empty?
assert_equal 2, @calculator.counter
end
def test_unmemoize_all
assert_equal 1, @calculator.counter
assert @calculator.instance_variable_get(:@_memoized_counter).any?
@calculator.unmemoize_all
assert @calculator.instance_variable_get(:@_memoized_counter).empty?
assert_equal 2, @calculator.counter
end
def test_memoize_all
@calculator.memoize_all
assert @calculator.instance_variable_defined?(:@_memoized_counter)
end
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 "Joshua", @person.update("Joshua")
end
def test_memoization_with_args
assert_equal 55, @calculator.fib(10)
assert_equal 11, @calculator.fib_calls
end
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
def test_memoization_with_boolean_arg
assert_equal 4, @calculator.add_or_subtract(2, 2, true)
assert_equal 2, @calculator.add_or_subtract(4, 2, false)
end
def test_object_memoization
[Company.new, Company.new, Company.new].each do |company|
company.extend Memoist
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 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_memoized_module_methods
company = Company.new
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
def test_double_memoization
assert_raise(RuntimeError) { Person.memoize :name }
person = Person.new
person.extend Memoist
assert_raise(RuntimeError) { person.memoize :name }
company = Company.new
company.extend Memoist
company.memoize :name
assert_raise(RuntimeError) { company.memoize :name }
end
def test_double_memoization_with_identifier
assert_nothing_raised { Person.memoize :name, :identifier => :again }
end
def test_memoization_with_a_subclass
student = Student.new
student.name
student.name
assert_equal 1, student.student_name_calls
assert_equal 1, student.name_calls
end
def test_protected_method_memoization
person = Person.new
assert_raise(NoMethodError) { person.memoize_protected_test }
assert_equal "protected", person.send(:memoize_protected_test)
end
def test_private_method_memoization
person = Person.new
assert_raise(NoMethodError) { person.is_developer? }
assert_equal "Yes", person.send(:is_developer?)
assert_equal 1, person.is_developer_calls
assert_equal "Yes", person.send(:is_developer?)
assert_equal 1, person.is_developer_calls
end
end
Jump to Line
Something went wrong with that request. Please try again.