Ruby LoadError with gmp - ruby

$ gem install gmp
Building native extensions. This could take a while...
Successfully installed gmp-0.7.43
Parsing documentation for gmp-0.7.43
Done installing documentation for gmp after 0 seconds
1 gem installed
$ cat gmp-test.rb
require 'gmp'
$ /opt/src/ruby-3.2.0/bin/ruby gmp-test.rb
<internal:/opt/src/ruby-3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require': cannot load such file -- /home/dunham/.local/share/gem/ruby/3.2.0/gems/gmp-0.7.43/lib/../ext/gmp (LoadError)
from <internal:/opt/src/ruby-3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
from /home/dunham/.local/share/gem/ruby/3.2.0/gems/gmp-0.7.43/lib/gmp.rb:9:in `<top (required)>'
from <internal:/opt/src/ruby-3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:159:in `require'
from <internal:/opt/src/ruby-3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:159:in `rescue in require'
from <internal:/opt/src/ruby-3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:149:in `require'
from gmp-test.rb:1:in `<main>'
<internal:/opt/src/ruby-3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require': cannot load such file -- gmp (LoadError)
from <internal:/opt/src/ruby-3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
from gmp-test.rb:1:in `<main>'

Library seems to be dead. It's expecting gmp.so to be in ext directory but it ends up in lib directory, it's probably new rubygems doing things differently.
>> require "gmp"
<internal:/home/alex/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in 'require':
cannot load such file -- /home/alex/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/gmp-0.7.43/lib/../ext/gmp (LoadError)
$ ls $(dirname $(gem which gmp))
gmp.rb gmp.so
# move ^ that to ../ext/
$ mv $(dirname $(gem which gmp))/gmp.so $(dirname $(gem which gmp))/../ext/
>> require "gmp"
=> true
>> GMP::Z(0)
=> 0
Update
From the linked logs looks like you're still not loading gmp.so which is where all the classes are defined. You can copy gmp.so into your app:
# copy `gmp.rb`
$ cp $(gem which gmp) .
# copy `gmp.so`
$ cp $(dirname $(gem which gmp))/gmp.so .
# or if you moved it to ext
$ cp $(dirname $(gem which gmp))/../ext/gmp.so .
$ touch app.rb
$ ls
app.rb gmp.rb gmp.so
gmp.rb defines GMP.sprintf method, if this is not a required method and you don't use it, you can remove this file.
# gmp.rb
# require 'rbconfig'
#
# ENV['PATH'] = [File.expand_path(
# File.join(File.dirname(__FILE__), "..", "ext")
# ), ENV['PATH']].compact.join(';') if RbConfig::CONFIG['host_os'] =~ /(mswin|mingw|mingw32)/i
#
# require File.dirname(__FILE__) + '/../ext/gmp'
# unless RUBY_VERSION =~ /^1.8/
module GMP
def self.sprintf(format, *args)
first_pct = format.index '%'
result = format[0...first_pct]
#format.gsub(/(?<!%)%[0#+ ']*[0-9]*.?[0-9]*[a-zA-Z][^%]*/) do |fragment|
format.gsub(Regexp.new('(?<!%)%[0#+ \']*[0-9]*.?[0-9]*[a-zA-Z][^%]*')) do |fragment|
arg = args.shift
if fragment =~ /%[0#+ ']*[0-9]*.?[0-9]*[ZQF]/
result << sprintf2(fragment, arg)
elsif fragment =~ /%[0#+ ']*[0-9]*.?[0-9]*[PR]/ && GMP.const_defined?(:MPFR_VERSION)
result << GMP::F.sprintf2(fragment, arg)
else
result << (fragment % arg)
end
end
result
end
end
# end
# app.rb
require_relative "gmp.so"
p GMP::Z
p GMP::Z(0)
p GMP::Q
p GMP::F
require_relative "gmp.rb"
p GMP.sprintf "%Zd", GMP.Z(0)
$ ruby --yjit -v
ruby 3.2.0 (2022-12-25 revision a528908271) +YJIT [x86_64-linux]
$ ruby --yjit app.rb
GMP::Z
0
GMP::Q
GMP::F
"0"

Related

OptionParser with subcommands

I'm trying to create a command line program with sub-commands using OptionParser. I'm following "ruby's OptionParser to get subcommands".
The problem is that it does not allow for a use case like this:
ruby main.rb --version
#=> main.rb in `<main>': undefined method `order!' for nil:NilClass (NoMethodError)
But it does allow for this:
ruby main.rb foo --options
ruby main.rb --options foo
ruby main.rb --options foo --options
How would I be properly handle command line arguments, in the case that no subcommand is given.
My example code is:
global = OptionParser.new do |opts|
opts.banner = "Usage: opt.rb [options] [subcommand [options]]"
opts.on("-v", "--version", "Print the version") do |v|
options[:version] = v
end
opts.separator ""
opts.separator subtext
end
The lines with the error:
global.order!
command = ARGV.shift
subcommands[command].order!
If global.order! uses all of ARGV, then command is nil. So... check for that.
global.order!
command = ARGV.shift
unless command
STDERR.puts "ERROR: no subcommand"
STDERR.puts global # prints usage
exit(-1)
end
subcommands[command].order!
Maybe this'll help:
require 'optparse'
VERSION = '1.0.0'
options = {}
OptionParser.new do |opt|
opt.on('-f', '--foo', 'Foo it') { |o| options[:foo] = o }
opt.on_tail('-v', '--version') do
puts VERSION
exit
end
end.parse!
puts options
Saving it as "test.rb" and running it with ruby test.rb returns:
{}
Running it with ruby test.rb -f or --foo returns:
{:foo=>true}
Running it with ruby test.rb -v or --version returns:
1.0.0
For more fun, running ruby test.rb -h or --help returns:
Usage: test [options]
-f, --foo Foo it
even though I didn't define -h or --help.
If I wanted the -v and --version flags to appear in the list then I'd change them from a on_tail method to a normal on method:
require 'optparse'
VERSION = '1.0.0'
options = {}
OptionParser.new do |opt|
opt.on('-f', '--foo', 'Foo it') { |o| options[:foo] = o }
opt.on('-v', '--version', 'Returns the version') do
puts VERSION
exit
end
end.parse!
puts options
which would return:
Usage: test [options]
-f, --foo Foo it
-v, --version Returns the version
I can add:
puts ARGV
to the end of the script and see that OptionParser is correctly handling flags and parameters:
>ruby test.rb bar --foo
{:foo=>true}
bar
>ruby test.rb --foo bar
{:foo=>true}
bar
See "Pass variables to Ruby script via command line" for more information.
There is no way your example code will handle your sample inputs using --options. No handler for --options is defined. Nor is subtext. Your code returns:
undefined local variable or method `subtext' for main:Object (NameError)
Stripping the block to:
global = OptionParser.new do |opts|
opts.on("-v", "--version", "Print the version") do |v|
options[:version] = v
end
end
and running again returns:
invalid option: --options (OptionParser::InvalidOption)
So, again, your example doesn't match the results you say you're getting.

Chef::DataBag and RSpec-mocks -- undefined method `recieve'

i am trying to create a list method stub for Chef::DataBag class as follows:
$ cat spec/spec_helper.rb
require "rspec"
RSpec.configure { |config|
config.mock_framework = :rspec
config.mock_with :rspec
}
$ cat spec/test_spec.rb
require "spec_helper"
require "chef"
RSpec.describe "test" do
describe "simple test" do
it "mocks chef databag" do
allow(Chef::DataBag).to recieve(:list).and_return {}
end
end
end
$ grep "rspec \|chef " Gemfile.lock | head -n 2
gem "chef", "11.16.4"
gem "rspec", "3.1.0"
when executing rspec i get the following error.
$ bundle exec rspec spec/test_spec.rb
F
Failures:
1) test simple test mocks chef databag
Failure/Error: allow(Chef::DataBag).to recieve(:list).and_return {}
NoMethodError:
undefined method `recieve' for #<RSpec::ExampleGroups::Test::SimpleTest:0x000000049964f8>
# ./spec/test_spec.rb:7:in `block (3 levels) in <top (required)>'
Finished in 0.00048 seconds (files took 0.53998 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/test_spec.rb:6 # test simple test mocks chef databag
that is how i verified that Chef::DataBag has the list method:
$ bundle exec ruby -e "require 'chef'; puts Chef::DataBag.methods" | grep list
list
can you please point out what is wrong?
You misspelled "receive." Try this:
allow(Chef::DataBag).to receive(:list).and_return {}

How can I write spec tests for puppet facts?

I have the following rb script which generate puppet facts according to the packages installed and which seems to be working ok in my puppet environment:
begin
pack = Facter::Core::Execution.execute('rpm -qa | grep ^ts')
packages = pack.split("\n")
packagehash = Hash.new
packages.each do |f|
packagehash[f.split("-")[0]] = f.split("-")[1] + ("-") + f.split("-")[2].split(".")[0]
end
rescue
end
begin
unless packagehash.empty?
packagehash.each_pair do |k,v|
Facter.add("bs_rpm_#{k}") {
setcode { "#{v}" }
}
end
end
rescue
end
I wrote the following spec which runs a small dummy test to see if my rspec env in general is ok:
require 'spec_helper'
describe 'bs package spec' do
before do
Facter.fact(:kernel).stubs(:value).returns("windows")
end
it "should run windows" do
Facter.fact(:kernel).value.should == "windows"
end
it "should create new facts" do
Facter::Core::Execution.stubs(:execute).with('rpm -qa | grep ^ts').returns('ts3_hostt01-1.0.0-34.x86_64\n')
Facter.fact(:bs_rpm_ts3_hostt01).value.should == "1.0.0-34"
end
end
But then when running rake spec I get the following error:
[dan#kyvltvm00022 bs_master]$ rake spec
/home/dan/.rvm/rubies/ruby-2.1.0/bin/ruby -S rspec spec/unit/facter/bs_package_spec.rb --color
.F
Failures:
1) bs package spec should create new facts
Failure/Error: Facter::Core::Execution.stubs(:execute).with('rpm -qa | grep ^ts').returns('ts3_hostt01-1.0.0-34.x86_64\n')
NameError:
uninitialized constant Facter::Core
# ./spec/unit/facter/bs_package_spec.rb:13:in `block (2 levels) in <top (required)>'
Finished in 0.00692 seconds
2 examples, 1 failure
Failed examples:
rspec ./spec/unit/facter/bs_package_spec.rb:12 # bs package spec should create new facts
/home/dan/.rvm/rubies/ruby-2.1.0/bin/ruby -S rspec spec/unit/facter/bs_package_spec.rb --color failed
[dan#kyvltvm00022 bs_master]$ exit
shell returned 1
[dan#kyvltvm00022 bs_master]$
What am I doing wrong or might be missing that is not loading Facter::Core ?? My spec_helper looks like this:
[dan#kyvltvm00022 bs_master]$ cat spec/spec_helper.rb
dir = File.expand_path(File.dirname(__FILE__))
$LOAD_PATH.unshift File.join(dir, 'lib')
# Don't want puppet getting the command line arguments for rake or autotest
ARGV.clear
require 'puppet'
require 'facter'
require 'mocha'
gem 'rspec', '>=2.0.0'
require 'rspec/expectations'
require 'puppetlabs_spec_helper/puppet_spec_helper'
RSpec.configure do |config|
# FIXME REVISIT - We may want to delegate to Facter like we do in
# Puppet::PuppetSpecInitializer.initialize_via_testhelper(config) because
# this behavior is a duplication of the spec_helper in Facter.
config.before :each do
# Ensure that we don't accidentally cache facts and environment between
# test cases. This requires each example group to explicitly load the
# facts being exercised with something like
# Facter.collection.loader.load(:ipaddress)
Facter::Util::Loader.any_instance.stubs(:load_all)
Facter.clear
Facter.clear_messages
end
end
[dan#kyvltvm00022 bs_master]$
[UPDATE]
After checking my test system I noticed the facter gem was missing core so I updated the code and test as follows:
pack is now:
pack = Facter::Util::Resolution.exec('rpm -qa | grep ^ts')
and the stub in my test now is:
Facter::Util::Resolution.stubs(:exec).with('rpm -qa | grep ^ts').returns('ts3_hostt01-1.0.0-34.x86_64\n')
And the result now is this:
[dan#kyvltvm00022 bs_master]$ rake spec
/home/dan/.rvm/rubies/ruby-2.1.0/bin/ruby -S rspec spec/unit/facter/bs_package_spec.rb --color
.F
Failures:
1) bs package spec should create new facts
Failure/Error: Facter.fact(:bs_rpm_ts3_hostt01).value.should == "1.0.0-34"
NoMethodError:
undefined method `value' for nil:NilClass
# ./spec/unit/facter/bs_package_spec.rb:14:in `block (2 levels) in <top (required)>'
Finished in 0.00747 seconds
2 examples, 1 failure
Failed examples:
rspec ./spec/unit/facter/bs_package_spec.rb:12 # bs package spec should create new facts
/home/dan/.rvm/rubies/ruby-2.1.0/bin/ruby -S rspec spec/unit/facter/bs_package_spec.rb --color failed
[dan#kyvltvm00022 bs_master]$
What am i doing wrong in my test?
Looking through the facter code, this is the file you're requiring:
https://github.com/puppetlabs/facter/blob/master/lib/facter.rb
It doesn't require core/execution itself... without digging too much further in could you just try this in your spec_helper:
require 'facter/core/execution'

Run def in ruby program

I'm a beginner in programming and wrote this little program:
Test.rb:
# encoding: utf-8
require 'open-uri'
require 'nokogiri'
def parse_file
doc = Nokogiri::XML(File.open("test.xml"))
parse_xml(doc)
end
def parse_xml(doc)
doc.root.elements.each do |node|
parse_tracks(node)
end
end
def parse_tracks(node)
if node.node_name.eql? 'kapitel'
puts 'New Kapitel'
end
end
I know how to execute this code:
ruby test.rb
But how can I call the def parse_file?
Simply add whatever you want to the end of your file. Ruby scripts are simply scripts, they are being interpreted:
…
end
parse_file # ⇐ HERE YOU GO
You can either call the method at the end of your test.rb file:
def parse_file
# ...
end
parse_file
And run it with
$ ruby test.rb
Or leave the file as it is, require it as a library and call the method manually:
$ ruby -r test.rb -e "parse_file"
Rather than hard-coding your file path, you can pass it as an argument when calling your script. Arguments can be accessed via the ARGV array:
def parse_file(file)
doc = Nokogiri::XML(File.open(file))
parse_xml(doc)
end
parse_file(ARGV.first)
Now you can run it with:
$ ruby test.rb test.xml
Another option is to make the script executable. Add a shebang as the first line of you file:
#!/usr/bin/env ruby
And set the execute flag:
$ chmod +x test.rb
Now you can run it with:
$ ./test.rb test.xml
just add
parse_file
in the end of your ruby file

one god for different rubies with rvm

I have two apps on my machine.
Each app (server) has it's own gemset and works on a different ruby version.
I will manage those apps with god which is installed in it's own gemset.
My god config file config.god looks like this:
God.watch do |w|
current_path = "/home/vagrant/server-1"
w.name = "server 1"
w.start = "ruby #{current_path}/simple-server.rb"
w.keepalive
end
God.watch do |w|
current_path = "/home/vagrant/server-2"
w.name = "server 2"
w.start = "ruby #{current_path}/simple-server.rb"
w.keepalive
end
My servers are simply writing the ruby version to a file (/home/vagrant/server-2/simple-server.rb):
require "date"
loop do
# simple console output
puts "Hello on #{RUBY_VERSION}, #{RUBY_PATCHLEVEL}, #{RUBY_PLATFORM}, #{RUBY_RELEASE_DATE}"
# Specify the name of the log file
log_file = File.join File.expand_path( File.dirname(__FILE__) ), "testfile.txt"
# Write the log into the file
File.open( log_file, 'a') do |f|
date = DateTime.now
date = date.strftime("%H:%M:%S")
f.puts "#{date} on #{RUBY_VERSION}, #{RUBY_PATCHLEVEL}, #{RUBY_PLATFORM}, #{RUBY_RELEASE_DATE}"
end
sleep 2
end
I run god with god -c config.god.
The problem is that my apps are not running with the ruby versions which is specified in the .rvmrc.
I have also tried:
~/.rvm/bin/wrapped_god -d config.god -D
rvmsudo ~/.rvm/bin/wrapped_god -d config.god -D
rvmsudo god -d config.god -D
Is there a solution for this case?
EDIT 2012.08.27:
I have changed my god config as follows:
w.start="~/.rvm/bin/rvm in #{current_path} do ruby simple-server.rb"
And it worked.
try:
start="~/.rvm/bin/rvm in #{current_path} do ruby simple-server.rb"

Resources