Module: Ref::Mock

Defined in:
lib/ref/mock.rb

Overview

This module provides mock weak and strong references that are designed to be used in tests. You can define a block where all weak and soft references created will be mock references. You can then mimic running the garbage collector on the objects pointed to by the references.

Example usage:

Ref::Mock.use do
  obj = Object.new
  ref = Ref::WeakReference.new(obj)
  ref.object   # obj
  Ref::Mock.gc(obj)  # mimics the garbage collector reclaiming the referenced object
  ref.object   # nil
end

Defined Under Namespace

Modules: MockReference Classes: MockSoftReference, MockWeakReference

Class Method Summary collapse

Class Method Details

.cleanupObject

Stop using mock references.



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/ref/mock.rb', line 85

def cleanup
  @object_space = nil
  class << ObjectSpace
    alias_method :define_finalizer_with_mock_reference, :define_finalizer
    alias_method :define_finalizer, :define_finalizer_without_mock_reference
  end
  
  class << WeakReference
    alias_method :new_with_mock_reference, :new
    alias_method :new, :new_without_mock_reference
  end
  
  class << SoftReference
    alias_method :new_with_mock_reference, :new
    alias_method :new, :new_without_mock_reference
  end
end

.gc(*objects) ⇒ Object

Simulate garbage collection of the objects passed in as arguments. If no objects are specified, all objects will be reclaimed.



109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/ref/mock.rb', line 109

def gc(*objects)
  objects = if objects.empty?
    object_space.keys
  else
    objects.map { |obj| obj.__id__ }
  end

  objects.each do |id|
    finalizers = object_space.delete(id)
    if finalizers
      finalizers.each{|finalizer| finalizer.call(id)}
    end
  end
end

.object_spaceObject

:nodoc:



103
104
105
# File 'lib/ref/mock.rb', line 103

def object_space # :nodoc:
  @object_space if instance_variable_defined?(:@object_space)
end

.setupObject

Start using mock references.



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/ref/mock.rb', line 33

def setup
  raise "Ref::Mock already setup" if object_space
  
  @object_space = {}
  
  class << ObjectSpace
    unless method_defined?(:define_finalizer_with_mock_reference)
      def define_finalizer_with_mock_reference(obj, finalizer)
        if ::Ref::Mock.object_space.include?(obj.__id__)
          ::Ref::Mock.object_space[obj.__id__] << finalizer
        else
          define_finalizer_without_mock_reference(obj, finalizer)
        end
      end
    end
    
    alias_method :define_finalizer_without_mock_reference, :define_finalizer
    alias_method :define_finalizer, :define_finalizer_with_mock_reference
  end
  
  class << WeakReference
    unless method_defined?(:new_with_mock_reference)
      def new_with_mock_reference(obj)
        if self == Mock::MockWeakReference
          new_without_mock_reference(obj)
        else
          Mock::MockWeakReference.new(obj)
        end
      end
    end
    
    alias_method :new_without_mock_reference, :new
    alias_method :new, :new_with_mock_reference
  end
  
  class << SoftReference
    unless method_defined?(:new_with_mock_reference)
      def new_with_mock_reference(obj)
        if self == Mock::MockSoftReference
          new_without_mock_reference(obj)
        else
          Mock::MockSoftReference.new(obj)
        end
      end
    end
    
    alias_method :new_without_mock_reference, :new
    alias_method :new, :new_with_mock_reference
  end
end

.useObject

Use the mock implementation inside a block and then restore the original implementation.



19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/ref/mock.rb', line 19

def use
  if object_space
    yield
  else
    setup
    begin
      yield
    ensure
      cleanup
    end
  end
end