require "helper"
class TestMemoryLeak < Nokogiri::TestCase
if ENV['NOKOGIRI_GC'] # turning these off by default for now
def test_dont_hurt_em_why
content = File.open("#{File.dirname(__FILE__)}/files/dont_hurt_em_why.xml").read
ndoc = Nokogiri::XML(content)
2.times do
info = ndoc.search('status text').first.inner_text
url = ndoc.search('user name').first.inner_text
GC.start
end
end
def test_for_memory_leak
begin
# we don't use Dike in any tests, but requiring it has side effects
# that can create memory leaks, and that's what we're testing for.
require 'rubygems'
require 'dike' # do not remove!
count_start = count_object_space_documents
xml_data = <<-EOS
- abc
- 1234
- Zzz
EOS
20.times do
doc = Nokogiri::XML(xml_data)
doc.xpath("//item")
end
2.times { GC.start }
count_end = count_object_space_documents
assert((count_end - count_start) <= 2, "memory leak detected")
rescue LoadError
puts "\ndike is not installed, skipping memory leak test"
end
end
if Nokogiri.ffi?
[ ['Node', 'p', nil],
['CDATA', nil, 'content'],
['Comment', nil, 'content'],
['DocumentFragment', nil],
['EntityReference', nil, 'p'],
['ProcessingInstruction', nil, 'p', 'content'] ].each do |klass, *args|
define_method "test_for_leaked_#{klass}_nodes" do
Nokogiri::LibXML.expects(:xmlAddChild).at_least(1) # more than once shows we're GCing properly
10.times {
xml = Nokogiri::XML("")
2.times { Nokogiri::XML.const_get(klass).new(*(args.collect{|arg| arg || xml})) }
GC.start
}
GC.start
end
end
def test_for_leaked_attr_nodes
Nokogiri::LibXML.expects(:xmlFreePropList).at_least(1) # more than once shows we're GCing properly
10.times {
xml = Nokogiri::XML("")
2.times { Nokogiri::XML::Attr.new(xml, "p") }
GC.start
}
GC.start
end
end # if ffi
end # if NOKOGIRI_GC
private
def count_object_space_documents
count = 0
ObjectSpace.each_object {|j| count += 1 if j.is_a?(Nokogiri::XML::Document) }
count
end
end