ruby_memcheck 0.1.2 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aa5f0f59617f5220d6870d3d44cae58605b9488c31d03c1c1d027895fafaf83d
4
- data.tar.gz: 999a0744c5a3c32ddf1e51d3f31164d13c144afe138fc4793b1930fcf3ec7a9e
3
+ metadata.gz: 7d7e2556e802cceebbd1607895ed319b54037e2a945586f8fe65e9f6bda0928c
4
+ data.tar.gz: 3cba76f62de7ad396458d651a272d660456e362a85c1c6a67ac6ae688b3e4c30
5
5
  SHA512:
6
- metadata.gz: f95821f8680a6685deb30e3a3acb8763878a52c76149f922f8a237f36406a0ded80e34dcbf66da29f78112e4fc4a4e3e534a7f6aa019a1df104c9e0d3cc18dbf
7
- data.tar.gz: 1d8cd567af6606c87b4222832917417a478e8ab265db59fffbc8ad4cd418bfd6bf06f63170ce537865972232134b503c23a661abdbdbc6b3f64d0ee2c7ca3a44
6
+ metadata.gz: 6e849c1bcfc9947293939452298c344acd71136dd7b617bb3edfc07c7b8122a9bc366e1e57a83d86293ed284569121185d465fd9e47959a9e9e0b6579b212022
7
+ data.tar.gz: 3131ae9a995bcd2e9f9fcab7f7bfb8b99c3449eadb12d9bfad0366681971d3c3fa7234e194fbf7e5c9a41583d18814cc59aad7802836ba1d075e0d6893be0e1d
data/.rubocop.yml CHANGED
@@ -3,3 +3,7 @@ inherit_gem:
3
3
 
4
4
  AllCops:
5
5
  SuggestExtensions: false
6
+
7
+ Style/GlobalVars:
8
+ Exclude:
9
+ - test/ruby_memcheck/ext/extconf.rb
data/README.md CHANGED
@@ -83,14 +83,15 @@ The easiest way to use this gem is to use it on your test suite using rake.
83
83
  RubyMemcheck::TestTask.new(valgrind: :compile, &test_config)
84
84
  end
85
85
  ```
86
- 1. In your `test_helper.rb`/`spec_helper.rb` (or whatever file sets up your test suite), add this line:
86
+ 1. At the top of your `test_helper.rb`/`spec_helper.rb` (or whatever file sets up your test suite), add this line:
87
87
 
88
88
  ```ruby
89
- END { GC.start }
89
+ at_exit { GC.start }
90
90
  ```
91
91
 
92
- This will ensure that the Garbage Collector is ran before Ruby shuts down. This will reduce the number of false-positives.
92
+ Place this line as close to the top of the file as possible, before any requires in the file (especially before the call to `require "minitest/autorun"`). This will ensure that the Garbage Collector is ran before Ruby shuts down. This will reduce the number of false-positives.
93
93
  1. You're ready to run your test suite with Valgrind using `rake test:valgrind`! Note that this will take a while to run because Valgrind will make Ruby significantly slower.
94
+ 1. (Optional) If you find false-positives in the output, you can create suppression files in a `suppressions` directory in the root directory of your gem. In this directory, you can create [Valgrind suppression files](https://wiki.wxwidgets.org/Valgrind_Suppression_File_Howto). The most basic suppression file is `your_binary_name_ruby.supp`. If you want some suppressions for only specific versions of Ruby, you can add the Ruby version to the filename. For example, `your_binary_name_ruby-3.supp` will suppress for any Rubies with a major version of 3 (e.g. 3.0.0, 3.1.1, etc.), while suppression file `your_binary_name_ruby-3.1.supp` will only be used for Ruby with a major and minor version of 3.1 (e.g. 3.1.0, 3.1.1, etc.).
94
95
 
95
96
  ## License
96
97
 
@@ -10,11 +10,13 @@ module RubyMemcheck
10
10
  "--leak-check=full",
11
11
  "--show-leak-kinds=definite",
12
12
  ].freeze
13
+ DEFAULT_VALGRIND_SUPPRESSIONS_DIR = "suppressions"
13
14
  DEFAULT_SKIPPED_RUBY_FUNCTIONS = [
14
15
  /\Arb_check_funcall/,
15
16
  /\Arb_enc_raise\z/,
16
17
  /\Arb_exc_raise\z/,
17
18
  /\Arb_funcall/,
19
+ /\Arb_intern/,
18
20
  /\Arb_ivar_set\z/,
19
21
  /\Arb_raise\z/,
20
22
  /\Arb_rescue/,
@@ -30,6 +32,7 @@ module RubyMemcheck
30
32
  ruby: FileUtils::RUBY,
31
33
  valgrind: DEFAULT_VALGRIND,
32
34
  valgrind_options: DEFAULT_VALGRIND_OPTIONS,
35
+ valgrind_suppressions_dir: DEFAULT_VALGRIND_SUPPRESSIONS_DIR,
33
36
  skipped_ruby_functions: DEFAULT_SKIPPED_RUBY_FUNCTIONS,
34
37
  valgrind_xml_file: Tempfile.new,
35
38
  output_io: $stderr
@@ -37,7 +40,9 @@ module RubyMemcheck
37
40
  @binary_name = binary_name
38
41
  @ruby = ruby
39
42
  @valgrind = valgrind
40
- @valgrind_options = valgrind_options
43
+ @valgrind_options =
44
+ valgrind_options +
45
+ get_valgrind_suppression_files(valgrind_suppressions_dir).map { |f| "--suppressions=#{f}" }
41
46
  @skipped_ruby_functions = skipped_ruby_functions
42
47
  @output_io = output_io
43
48
 
@@ -89,5 +94,18 @@ module RubyMemcheck
89
94
  false
90
95
  end
91
96
  end
97
+
98
+ private
99
+
100
+ def get_valgrind_suppression_files(dir)
101
+ full_ruby_version = "#{RUBY_ENGINE}-#{RUBY_VERSION}.#{RUBY_PATCHLEVEL}"
102
+ versions = [full_ruby_version]
103
+ (0..3).reverse_each { |i| versions << full_ruby_version.split(".")[0, i].join(".") }
104
+ versions << RUBY_ENGINE
105
+
106
+ versions.map do |version|
107
+ Dir[File.join(dir, "#{binary_name}_#{version}.supp")]
108
+ end.flatten
109
+ end
92
110
  end
93
111
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyMemcheck
4
+ class Suppression
5
+ attr_reader :root
6
+
7
+ def initialize(configuration, suppression_node)
8
+ @root = suppression_node
9
+ end
10
+
11
+ def to_s
12
+ return "" if root.nil?
13
+
14
+ str = StringIO.new
15
+ str << "{\n"
16
+ str << " #{root.at_xpath("sname").content}\n"
17
+ str << " #{root.at_xpath("skind").content}\n"
18
+ root.xpath("./sframe/fun | ./sframe/obj").each do |frame|
19
+ str << " #{frame.name}:#{frame.content}\n"
20
+ end
21
+ str << "}\n"
22
+ str.string
23
+ end
24
+ end
25
+ end
@@ -20,7 +20,7 @@ module RubyMemcheck
20
20
  def ruby(*args, **options, &block)
21
21
  command = configuration.command(args)
22
22
  sh(command, **options) do |ok, res|
23
- if ok && configuration.valgrind_xml_file
23
+ if configuration.valgrind_xml_file
24
24
  parse_valgrind_output
25
25
  unless errors.empty?
26
26
  output_valgrind_errors
@@ -35,10 +35,13 @@ module RubyMemcheck
35
35
  private
36
36
 
37
37
  def parse_valgrind_output
38
+ require "nokogiri"
39
+
38
40
  @errors = []
39
41
 
40
- xml = Nokogiri::XML(configuration.valgrind_xml_file.read)
41
- xml.xpath("/valgrindoutput/error").each do |error_xml|
42
+ Nokogiri::XML::Reader(File.open(configuration.valgrind_xml_file.to_path)).each do |node|
43
+ next unless node.name == "error" && node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT
44
+ error_xml = Nokogiri::XML::Document.parse(node.outer_xml).root
42
45
  error = ValgrindError.new(configuration, error_xml)
43
46
  next if error.skip?
44
47
  @errors << error
@@ -2,7 +2,7 @@
2
2
 
3
3
  module RubyMemcheck
4
4
  class ValgrindError
5
- attr_reader :kind, :msg, :stack
5
+ attr_reader :kind, :msg, :stack, :suppression
6
6
 
7
7
  def initialize(configuration, error)
8
8
  @kind = error.at_xpath("kind").content
@@ -14,6 +14,7 @@ module RubyMemcheck
14
14
  end
15
15
  @stack = Stack.new(configuration, error.at_xpath("stack"))
16
16
  @configuration = configuration
17
+ @suppression = Suppression.new(configuration, error.at_xpath("suppression"))
17
18
  end
18
19
 
19
20
  def skip?
@@ -34,6 +35,7 @@ module RubyMemcheck
34
35
  " #{frame}\n"
35
36
  end
36
37
  end
38
+ str << suppression.to_s
37
39
  str.string
38
40
  end
39
41
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyMemcheck
4
- VERSION = "0.1.2"
4
+ VERSION = "0.2.1"
5
5
  end
data/lib/ruby_memcheck.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "tempfile"
4
- require "nokogiri"
5
4
  require "rake/testtask"
6
5
 
7
6
  require "ruby_memcheck/configuration"
@@ -9,6 +8,7 @@ require "ruby_memcheck/frame"
9
8
  require "ruby_memcheck/stack"
10
9
  require "ruby_memcheck/test_task"
11
10
  require "ruby_memcheck/valgrind_error"
11
+ require "ruby_memcheck/suppression"
12
12
  require "ruby_memcheck/version"
13
13
 
14
14
  module RubyMemcheck
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_memcheck
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Zhu
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-10-18 00:00:00.000000000 Z
11
+ date: 2021-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -94,7 +94,7 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '2.3'
97
- description:
97
+ description:
98
98
  email:
99
99
  - peter@peterzhu.ca
100
100
  executables: []
@@ -113,6 +113,7 @@ files:
113
113
  - lib/ruby_memcheck/configuration.rb
114
114
  - lib/ruby_memcheck/frame.rb
115
115
  - lib/ruby_memcheck/stack.rb
116
+ - lib/ruby_memcheck/suppression.rb
116
117
  - lib/ruby_memcheck/test_task.rb
117
118
  - lib/ruby_memcheck/valgrind_error.rb
118
119
  - lib/ruby_memcheck/version.rb
@@ -122,7 +123,7 @@ licenses:
122
123
  - MIT
123
124
  metadata:
124
125
  homepage_uri: https://github.com/peterzhu2118/ruby_memcheck
125
- post_install_message:
126
+ post_install_message:
126
127
  rdoc_options: []
127
128
  require_paths:
128
129
  - lib
@@ -137,8 +138,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
137
138
  - !ruby/object:Gem::Version
138
139
  version: '0'
139
140
  requirements: []
140
- rubygems_version: 3.2.15
141
- signing_key:
141
+ rubygems_version: 3.3.0.dev
142
+ signing_key:
142
143
  specification_version: 4
143
144
  summary: Use Valgrind memcheck without going crazy
144
145
  test_files: []