Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support --gen-suppressions #4

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/ruby_memcheck.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
require "ruby_memcheck/stack"
require "ruby_memcheck/test_task"
require "ruby_memcheck/valgrind_error"
require "ruby_memcheck/suppression"
require "ruby_memcheck/version"

module RubyMemcheck
Expand Down
25 changes: 25 additions & 0 deletions lib/ruby_memcheck/suppression.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

module RubyMemcheck
class Suppression
attr_reader :root

def initialize(configuration, suppression_node)
@root = suppression_node
end

def to_s
return "" if root.nil?

str = StringIO.new
str << "{\n"
str << " #{root.at_xpath("sname").content}\n"
str << " #{root.at_xpath("skind").content}\n"
root.xpath("./sframe/fun | ./sframe/obj").each do |frame|
str << " #{frame.name}:#{frame.content}\n"
end
str << "}\n"
str.string
end
end
end
4 changes: 3 additions & 1 deletion lib/ruby_memcheck/valgrind_error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module RubyMemcheck
class ValgrindError
attr_reader :kind, :msg, :stack
attr_reader :kind, :msg, :stack, :suppression

def initialize(configuration, error)
@kind = error.at_xpath("kind").content
Expand All @@ -14,6 +14,7 @@ def initialize(configuration, error)
end
@stack = Stack.new(configuration, error.at_xpath("stack"))
@configuration = configuration
@suppression = Suppression.new(configuration, error.at_xpath("suppression"))
end

def skip?
Expand All @@ -34,6 +35,7 @@ def to_s
" #{frame}\n"
end
end
str << suppression.to_s
str.string
end

Expand Down
53 changes: 53 additions & 0 deletions test/ruby_memcheck/ruby_memcheck_suppression_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

require "test_helper"
require "nokogiri"

module RubyMemcheck
class RubyMemcheckSuppressionTest < Minitest::Test
def setup
@configuration = Configuration.new(
binary_name: "ruby_memcheck_c_test",
output_io: @output_io,
)
end

def test_given_nil
assert_equal("", RubyMemcheck::Suppression.new(@configuration, nil).to_s)
end

def test_given_a_suppression_node
suppression = ::Nokogiri::XML(<<~EOF).at_xpath("//suppression")
<foo>
<suppression>
<sname>insert_a_suppression_name_here</sname>
<skind>Memcheck:Leak</skind>
<skaux>match-leak-kinds: definite</skaux>
<sframe> <fun>malloc</fun> </sframe>
<sframe> <fun>objspace_xmalloc0</fun> </sframe>
<sframe> <fun>ruby_xmalloc0</fun> </sframe>
<sframe> <obj>/usr/lib/libX11.so.6.3.0</fun> </sframe>
<sframe> <fun>ruby_xmalloc_body</fun> </sframe>
<sframe> <fun>ruby_xmalloc</fun> </sframe>
</suppression>
</foo>
EOF
expected = <<~EOF
{
insert_a_suppression_name_here
Memcheck:Leak
fun:malloc
fun:objspace_xmalloc0
fun:ruby_xmalloc0
obj:/usr/lib/libX11.so.6.3.0
fun:ruby_xmalloc_body
fun:ruby_xmalloc
}
EOF
assert_equal(
expected,
RubyMemcheck::Suppression.new(@configuration, suppression).to_s,
)
end
end
end
22 changes: 22 additions & 0 deletions test/ruby_memcheck/ruby_memcheck_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,28 @@ def test_suppressions
assert_empty(@output_io.string)
end

def test_generation_of_suppressions
valgrind_options = RubyMemcheck::Configuration::DEFAULT_VALGRIND_OPTIONS.dup
valgrind_options << "--gen-suppressions=all"
build_configuration(valgrind_options: valgrind_options)

assert_raises(RubyMemcheck::TestTask::VALGRIND_REPORT_MSG) do
run_with_memcheck(<<~RUBY)
RubyMemcheck::CTest.new.memory_leak
RUBY
end

assert_equal(1, @test_task.errors.length)

output = @output_io.string
refute_empty(output)
assert_match(/^100 bytes in 1 blocks are definitely lost in loss record/, output)
assert_match(/^ \*memory_leak \(ruby_memcheck_c_test\.c:\d+\)$/, output)
assert_match(/^ insert_a_suppression_name_here/, output)
assert_match(/^ Memcheck:Leak/, output)
assert_match(/^ fun:allocate_memory_leak/, output)
end

def test_reports_multiple_errors
assert_raises(RubyMemcheck::TestTask::VALGRIND_REPORT_MSG) do
run_with_memcheck(<<~RUBY)
Expand Down