2022-03-16 07:52:46 -04:00
|
|
|
# frozen_string_literal: true
|
2022-06-23 05:22:36 -04:00
|
|
|
|
2022-03-16 07:52:46 -04:00
|
|
|
require_relative 'helper'
|
|
|
|
require 'rubygems/ext'
|
|
|
|
|
|
|
|
class TestGemExtCargoBuilder < Gem::TestCase
|
|
|
|
def setup
|
2022-04-06 13:32:32 -04:00
|
|
|
super
|
2022-03-16 07:52:46 -04:00
|
|
|
|
|
|
|
@rust_envs = {
|
2022-06-23 05:22:36 -04:00
|
|
|
'CARGO_HOME' => ENV.fetch('CARGO_HOME', File.join(@orig_env['HOME'], '.cargo')),
|
|
|
|
'RUSTUP_HOME' => ENV.fetch('RUSTUP_HOME', File.join(@orig_env['HOME'], '.rustup')),
|
2022-03-16 07:52:46 -04:00
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
def setup_rust_gem(name)
|
|
|
|
@ext = File.join(@tempdir, 'ext')
|
|
|
|
@dest_path = File.join(@tempdir, 'prefix')
|
2022-04-01 07:36:59 -04:00
|
|
|
@fixture_dir = Pathname.new(File.expand_path("test_gem_ext_cargo_builder/#{name}/", __dir__))
|
2022-03-16 07:52:46 -04:00
|
|
|
|
|
|
|
FileUtils.mkdir_p @dest_path
|
|
|
|
FileUtils.cp_r(@fixture_dir.to_s, @ext)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_build_staticlib
|
|
|
|
skip_unsupported_platforms!
|
|
|
|
setup_rust_gem "rust_ruby_example"
|
|
|
|
|
|
|
|
content = @fixture_dir.join('Cargo.toml').read.gsub("cdylib", "staticlib")
|
|
|
|
File.write(File.join(@ext, 'Cargo.toml'), content)
|
|
|
|
|
|
|
|
output = []
|
|
|
|
|
|
|
|
Dir.chdir @ext do
|
|
|
|
ENV.update(@rust_envs)
|
|
|
|
spec = Gem::Specification.new 'rust_ruby_example', '0.1.0'
|
|
|
|
builder = Gem::Ext::CargoBuilder.new(spec)
|
|
|
|
assert_raise(Gem::Ext::CargoBuilder::DylibNotFoundError) do
|
|
|
|
builder.build nil, @dest_path, output
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_build_cdylib
|
|
|
|
skip_unsupported_platforms!
|
|
|
|
setup_rust_gem "rust_ruby_example"
|
|
|
|
|
|
|
|
output = []
|
|
|
|
|
|
|
|
Dir.chdir @ext do
|
|
|
|
ENV.update(@rust_envs)
|
|
|
|
spec = Gem::Specification.new 'rust_ruby_example', '0.1.0'
|
|
|
|
builder = Gem::Ext::CargoBuilder.new(spec)
|
|
|
|
builder.build nil, @dest_path, output
|
|
|
|
end
|
|
|
|
|
|
|
|
output = output.join "\n"
|
|
|
|
bundle = File.join(@dest_path, "release/rust_ruby_example.#{RbConfig::CONFIG['DLEXT']}")
|
|
|
|
|
2022-06-23 05:22:36 -04:00
|
|
|
assert_match "Finished release [optimized] target(s)", output
|
|
|
|
assert_ffi_handle bundle, 'Init_rust_ruby_example'
|
|
|
|
rescue Exception => e
|
|
|
|
pp output if output
|
|
|
|
|
|
|
|
raise(e)
|
|
|
|
end
|
2022-03-16 07:52:46 -04:00
|
|
|
|
2022-06-23 05:22:36 -04:00
|
|
|
def test_build_dev_profile
|
|
|
|
skip_unsupported_platforms!
|
|
|
|
setup_rust_gem "rust_ruby_example"
|
2022-03-16 07:52:46 -04:00
|
|
|
|
2022-06-23 05:22:36 -04:00
|
|
|
output = []
|
|
|
|
|
|
|
|
Dir.chdir @ext do
|
|
|
|
ENV.update(@rust_envs)
|
|
|
|
spec = Gem::Specification.new 'rust_ruby_example', '0.1.0'
|
|
|
|
builder = Gem::Ext::CargoBuilder.new(spec)
|
|
|
|
builder.profile = :dev
|
|
|
|
builder.build nil, @dest_path, output
|
|
|
|
end
|
|
|
|
|
|
|
|
output = output.join "\n"
|
|
|
|
bundle = File.join(@dest_path, "debug/rust_ruby_example.#{RbConfig::CONFIG['DLEXT']}")
|
|
|
|
|
|
|
|
assert_match "Finished dev [unoptimized + debuginfo] target(s)", output
|
|
|
|
assert_ffi_handle bundle, 'Init_rust_ruby_example'
|
2022-03-16 07:52:46 -04:00
|
|
|
rescue Exception => e
|
|
|
|
pp output if output
|
|
|
|
|
|
|
|
raise(e)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_build_fail
|
|
|
|
skip_unsupported_platforms!
|
|
|
|
setup_rust_gem "rust_ruby_example"
|
|
|
|
|
|
|
|
output = []
|
|
|
|
|
|
|
|
FileUtils.rm(File.join(@ext, 'src/lib.rs'))
|
|
|
|
|
|
|
|
error = assert_raise(Gem::InstallError) do
|
|
|
|
Dir.chdir @ext do
|
|
|
|
ENV.update(@rust_envs)
|
|
|
|
spec = Gem::Specification.new 'rust_ruby_example', '0.1.0'
|
|
|
|
builder = Gem::Ext::CargoBuilder.new(spec)
|
|
|
|
builder.build nil, @dest_path, output
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
output = output.join "\n"
|
|
|
|
|
|
|
|
assert_match 'cargo failed', error.message
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_full_integration
|
|
|
|
skip_unsupported_platforms!
|
|
|
|
setup_rust_gem "rust_ruby_example"
|
|
|
|
|
2022-06-23 05:22:36 -04:00
|
|
|
require 'open3'
|
|
|
|
|
2022-03-16 07:52:46 -04:00
|
|
|
Dir.chdir @ext do
|
|
|
|
require 'tmpdir'
|
|
|
|
|
2022-06-23 05:22:36 -04:00
|
|
|
env_for_subprocess = @rust_envs.merge("GEM_HOME" => Gem.paths.home)
|
|
|
|
gem = [env_for_subprocess, *ruby_with_rubygems_in_load_path, File.expand_path('../../bin/gem', __dir__)]
|
2022-03-16 07:52:46 -04:00
|
|
|
|
|
|
|
Dir.mktmpdir("rust_ruby_example") do |dir|
|
|
|
|
built_gem = File.expand_path(File.join(dir, "rust_ruby_example.gem"))
|
|
|
|
Open3.capture2e(*gem, "build", "rust_ruby_example.gemspec", "--output", built_gem)
|
|
|
|
Open3.capture2e(*gem, "install", "--verbose", "--local", built_gem, *ARGV)
|
|
|
|
|
2022-06-23 05:22:36 -04:00
|
|
|
stdout_and_stderr_str, status = Open3.capture2e(env_for_subprocess, *ruby_with_rubygems_in_load_path, "-rrust_ruby_example", "-e", "puts 'Result: ' + RustRubyExample.reverse('hello world')")
|
|
|
|
assert status.success?, stdout_and_stderr_str
|
|
|
|
assert_match "Result: #{"hello world".reverse}", stdout_and_stderr_str
|
|
|
|
end
|
2022-03-16 07:52:46 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_custom_name
|
|
|
|
skip_unsupported_platforms!
|
|
|
|
setup_rust_gem "custom_name"
|
|
|
|
|
|
|
|
Dir.chdir @ext do
|
|
|
|
require 'tmpdir'
|
|
|
|
|
2022-06-23 05:22:36 -04:00
|
|
|
env_for_subprocess = @rust_envs.merge("GEM_HOME" => Gem.paths.home)
|
|
|
|
gem = [env_for_subprocess, *ruby_with_rubygems_in_load_path, File.expand_path('../../bin/gem', __dir__)]
|
2022-03-16 07:52:46 -04:00
|
|
|
|
|
|
|
Dir.mktmpdir("custom_name") do |dir|
|
|
|
|
built_gem = File.expand_path(File.join(dir, "custom_name.gem"))
|
|
|
|
Open3.capture2e(*gem, "build", "custom_name.gemspec", "--output", built_gem)
|
|
|
|
Open3.capture2e(*gem, "install", "--verbose", "--local", built_gem, *ARGV)
|
|
|
|
end
|
|
|
|
|
2022-06-23 05:22:36 -04:00
|
|
|
stdout_and_stderr_str, status = Open3.capture2e(env_for_subprocess, *ruby_with_rubygems_in_load_path, "-rcustom_name", "-e", "puts 'Result: ' + CustomName.say_hello")
|
2022-03-16 07:52:46 -04:00
|
|
|
|
|
|
|
assert status.success?, stdout_and_stderr_str
|
|
|
|
assert_match "Result: Hello world!", stdout_and_stderr_str
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-06-23 05:22:36 -04:00
|
|
|
private
|
|
|
|
|
2022-03-16 07:52:46 -04:00
|
|
|
def skip_unsupported_platforms!
|
|
|
|
pend "jruby not supported" if java_platform?
|
|
|
|
pend "truffleruby not supported (yet)" if RUBY_ENGINE == 'truffleruby'
|
|
|
|
pend "mswin not supported (yet)" if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS')
|
2022-06-23 05:22:36 -04:00
|
|
|
system(@rust_envs, 'cargo', '-V', out: IO::NULL, err: [:child, :out])
|
|
|
|
pend 'cargo not present' unless $?.success?
|
|
|
|
pend "ruby.h is not provided by ruby repo" if ruby_repo?
|
|
|
|
end
|
|
|
|
|
|
|
|
def assert_ffi_handle(bundle, name)
|
|
|
|
require 'fiddle'
|
|
|
|
dylib_handle = Fiddle.dlopen bundle
|
|
|
|
assert_nothing_raised { dylib_handle[name] }
|
2022-03-16 07:52:46 -04:00
|
|
|
end
|
|
|
|
end
|