Skip to content

Commit

Permalink
Merge pull request #24 from Shopify/ruby-script-support
Browse files Browse the repository at this point in the history
Add running on a Ruby script
  • Loading branch information
peterzhu2118 authored Aug 14, 2023
2 parents b4ce665 + e644025 commit 28a60a5
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 3 deletions.
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ This gem provides a sane way to use Valgrind's memcheck on your native extension
1. [How does it work?](#how-does-it-work)
1. [Limitations](#limitations)
1. [Installation](#installation)
1. [Setup](#setup)
1. [Running a Ruby script](#running-a-ruby-script)
1. [Setup for test suites](#setup-for-test-suites)
1. [Configuration](#configuration)
1. [Suppression files](#suppression-files)
1. [License](#license)
Expand Down Expand Up @@ -48,7 +49,16 @@ Because of the aggressive heuristics used to filter out false positives, there a
gem install ruby_memcheck
```

## Setup
## Running a Ruby script

You can run a Ruby script under ruby_memcheck. This will report all memory leaks in all native extensions found in your Ruby script. Simply replace the `ruby` part of your command with `ruby_memcheck`. For example:

```sh
$ ruby_memcheck -e "puts 'Hello world'"
Hello world
```

## Setup for test suites

> **Note**
> If you encounter errors from Valgrind that looks like this:
Expand All @@ -69,7 +79,7 @@ gem install ruby_memcheck
> sudo make install
> ```
The easiest way to use this gem is to use it on your test suite (minitest or RSpec) using rake.
You can use ruby_memcheck on your test suite (Minitest or RSpec) using rake.
0. Install Valgrind.
1. In your Rakefile, require this gem.
Expand Down
9 changes: 9 additions & 0 deletions exe/ruby_memcheck
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

$LOAD_PATH.unshift("#{__dir__}/../lib")

require "ruby_memcheck"

runner = RubyMemcheck::RubyRunner.new
exit(runner.run(*ARGV))
3 changes: 3 additions & 0 deletions lib/ruby_memcheck.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# frozen_string_literal: true

require "English"
require "shellwords"
require "tempfile"
require "rake/testtask"

require "ruby_memcheck/configuration"
require "ruby_memcheck/frame"
require "ruby_memcheck/ruby_runner"
require "ruby_memcheck/stack"
require "ruby_memcheck/test_task_reporter"
require "ruby_memcheck/test_task"
Expand Down
32 changes: 32 additions & 0 deletions lib/ruby_memcheck/ruby_runner.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# frozen_string_literal: true

module RubyMemcheck
class RubyRunner
attr_reader :configuration
attr_reader :reporter

def initialize(*args)
@configuration =
if !args.empty? && args[0].is_a?(Configuration)
args.shift
else
RubyMemcheck.default_configuration
end
end

def run(*args, **options)
command = configuration.command(args.map { |a| Shellwords.escape(a) })

@reporter = TestTaskReporter.new(configuration)

@reporter.setup

system(command, options)
exit_code = $CHILD_STATUS.exitstatus

@reporter.report_valgrind_errors

exit_code
end
end
end
42 changes: 42 additions & 0 deletions test/ruby_memcheck/ruby_runner_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# frozen_string_literal: true

require "ruby_memcheck/shared_test_task_reporter_tests"

module RubyMemcheck
class RubyRunnerTest < Minitest::Test
include SharedTestTaskReporterTests

def setup
@output_io = StringIO.new
build_configuration
end

private

def run_with_memcheck(code, raise_on_failure: true, spawn_opts: {})
script = Tempfile.new
script.write(<<~RUBY)
require "ruby_memcheck_c_test_one"
require "ruby_memcheck_c_test_two"
#{code}
RUBY
script.flush

exit_code = @test_task.run(
"-I#{File.join(__dir__, "ext")}",
script.path,
**spawn_opts,
)

if raise_on_failure && exit_code != 0
raise "Command failed with status (#{exit_code})"
end

exit_code == 0
end

def build_test_task
@test_task = RubyMemcheck::RubyRunner.new(@configuration)
end
end
end

0 comments on commit 28a60a5

Please sign in to comment.