Class: Async::RSpec::Memory::LimitAllocations

Inherits:
Object
  • Object
show all
Includes:
RSpec::Matchers::Composable
Defined in:
lib/async/rspec/memory/limit_allocations.rb

Overview

expect….to allocate < 10.megabytes

Instance Method Summary collapse

Constructor Details

#initialize(allocations = {}, count: nil, size: nil) ⇒ LimitAllocations

Returns a new instance of LimitAllocations.



34
35
36
37
38
39
40
41
42
43
44
# File 'lib/async/rspec/memory/limit_allocations.rb', line 34

def initialize(allocations = {}, count: nil, size: nil)
  @count = count
  @size = size
  
  @allocations = {}
  @errors = []
  
  allocations.each do |klass, count|
    self.of(klass, count: count)
  end
end

Instance Method Details

#failure_messageObject



105
106
107
# File 'lib/async/rspec/memory/limit_allocations.rb', line 105

def failure_message
  "exceeded allocation limit: #{@errors.join(', ')}"
end

#matches?(given_proc) ⇒ Boolean

Returns:

  • (Boolean)


69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/async/rspec/memory/limit_allocations.rb', line 69

def matches?(given_proc)
  return true unless trace = Trace.capture(@allocations.keys, &given_proc)
  
  if @count or @size
    # If the spec specifies a total limit, we have a limit which we can enforce which takes all allocations into account:
    total = trace.total
    
    check(total.count, @count) do |expected|
      @errors << "allocated #{total.count} instances, #{total.size} bytes, #{expected} instances"
    end if @count
    
    check(total.size, @size) do |expected|
      @errors << "allocated #{total.count} instances, #{total.size} bytes, #{expected} bytes"
    end if @size
  else
    # Otherwise unspecified allocations are considered an error:
    trace.ignored.each do |klass, allocation|
      @errors << "allocated #{allocation.count} #{klass} instances, #{allocation.size} bytes, but it was not specified"
    end
  end
  
  trace.allocated.each do |klass, allocation|
    next unless acceptable = @allocations[klass]
    
    check(allocation.count, acceptable[:count]) do |expected|
      @errors << "allocated #{allocation.count} #{klass} instances, #{allocation.size} bytes, #{expected} instances"
    end
    
    check(allocation.size, acceptable[:size]) do |expected|
      @errors << "allocated #{allocation.count} #{klass} instances, #{allocation.size} bytes, #{expected} bytes"
    end
  end
  
  return @errors.empty?
end

#of(klass, **limits) ⇒ Object



50
51
52
53
54
# File 'lib/async/rspec/memory/limit_allocations.rb', line 50

def of(klass, **limits)
  @allocations[klass] = limits
  
  return self
end

#supports_block_expectations?Boolean

Returns:

  • (Boolean)


46
47
48
# File 'lib/async/rspec/memory/limit_allocations.rb', line 46

def supports_block_expectations?
  true
end