Skip to content

Commit

Permalink
Merge pull request #134 from ancorgs/rspec_scr
Browse files Browse the repository at this point in the history
Added Yast::RSpec::SCR extension
  • Loading branch information
ancorgs committed Jan 26, 2015
2 parents ef1d3c8 + 6012867 commit 7deaa82
Show file tree
Hide file tree
Showing 10 changed files with 290 additions and 3 deletions.
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,29 @@ content = ButtonBox(

### Testing

The YaST team encourages to use RSpec for testing YaST code in Ruby. There is
a plan to create a helper to allow easier testing.
The YaST team encourages to use RSpec for testing YaST code in Ruby. To help in
that task, this gem includes some RSpec extensions under the {Yast::RSpec}
namespace. In order to use these extensions, the following line must be added
to the tests.

```ruby
require 'yast/rspec'
```

For example, the following code makes use of the #path helper provided by
{Yast::RSpec::Shortcuts}.

```ruby

require 'yast/rspec'

describe ".proc.meminfo agent" do
it "returns a Hash" do
value = Yast::SCR.Read(path(".proc.meminfo"))
expect(value).to be_a(Hash)
end
end
```

### Further Information

Expand Down
6 changes: 6 additions & 0 deletions package/yast2-ruby-bindings.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Thu Jan 22 11:46:58 UTC 2015 - ancor@suse.com

- Added some RSpec helpers to easy the development of tests
- 3.1.26

-------------------------------------------------------------------
Mon Oct 20 11:59:06 UTC 2014 - lslezak@suse.cz

Expand Down
2 changes: 1 addition & 1 deletion package/yast2-ruby-bindings.spec
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@


Name: yast2-ruby-bindings
Version: 3.1.25
Version: 3.1.26
Url: https://github.com/yast/yast-ruby-bindings
Release: 0
BuildRoot: %{_tmppath}/%{name}-%{version}-build
Expand Down
2 changes: 2 additions & 0 deletions src/ruby/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
add_definitions(-DY2LOG=\"Ruby\")

FILE(GLOB files "${CMAKE_CURRENT_SOURCE_DIR}/*/*.rb")
FILE(GLOB rspec "${CMAKE_CURRENT_SOURCE_DIR}/yast/rspec/*.rb")
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/yast.rb DESTINATION ${RUBY_VENDORLIB_DIR} )
INSTALL(FILES ${files} DESTINATION ${RUBY_VENDORLIB_DIR}/yast)
INSTALL(FILES ${rspec} DESTINATION ${RUBY_VENDORLIB_DIR}/yast/rspec)

7 changes: 7 additions & 0 deletions src/ruby/yast/rspec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'yast/rspec/scr'
require 'yast/rspec/shortcuts'

RSpec.configure do |c|
c.include Yast::RSpec::Shortcuts
c.include Yast::RSpec::SCR
end
101 changes: 101 additions & 0 deletions src/ruby/yast/rspec/scr.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
require "rspec"
require "yast"

module Yast
module RSpec
# RSpec extension to handle several agent operations.
module SCR
# Encapsulates SCR calls into a chroot.
#
# If a block if given, the SCR calls in the block are executed in the
# chroot and the corresponding SCR instance is automatically closed when
# the block ends (or if an exception is raised by the block).
#
# If a block is not given, the chroot must be explicitly closed calling
# reset_root_path.
#
# Nesting of chroots is forbidden and the method will raise an exception
# if is called without closing a previous chroot.
#
# @param directory [#to_s] directory to use as '/' for SCR calls
#
# @example Usage with a block
# change_scr_root("/home/chroot1") do
# # This reads the content of /home/chroot1/
# Yast::SCR.Read(path(".target.dir"), "/")
# end
#
# @example Usage without a block
# change_scr_root("/home/chroot1")
# # This reads the content of /home/chroot1/
# Yast::SCR.Read(path(".target.dir"), "/")
# reset_scr_root
#
# @example Usage within RSpec
# describe YaST::SCR do
# around { |example| change_scr_root("/home/chroot1", &example) }
#
# describe "#Read" do
# it "works with the .proc.meminfo path"
# # This reads from /home/chroot1/proc/meminfo
# values = Yast::SCR.Read(path(".proc.meminfo"))
# expect(values).to include("key" => "value")
# end
# end
# end
def change_scr_root(directory)
if @scr_handle
raise "There is already an open chrooted SCR instance, "\
"a call to reset_scr_root was expected"
end

if !File.directory?(directory)
raise "#{directory} is not a valid directory"
end

@scr_original_handle = Yast::WFM.SCRGetDefault
check_version = false
@scr_handle = Yast::WFM.SCROpen("chroot=#{directory}:scr", check_version)
if @scr_handle < 0
@scr_handle = nil
@scr_original_handle = nil
raise "Error creating the chrooted SCR instance"
end
Yast::WFM.SCRSetDefault(@scr_handle)

if block_given?
begin
yield
ensure
reset_scr_root
end
end
end

# Resets the SCR calls to prior behaviour, closing the SCR instance open
# by the call to #change_scr_root.
#
# Raises an exception if #change_scr_root has not been called before or if
# the corresponding instance has already been closed.
#
# @see #change_scr_root
def reset_scr_root
if @scr_handle.nil?
raise "Unable to find a chrooted SCR instance to close"
end

default_handle = Yast::WFM.SCRGetDefault
if default_handle != @scr_handle
raise "Error closing the chrooted SCR instance, "\
"it's not the current default one"
end

Yast::WFM.SCRClose(default_handle)
Yast::WFM.SCRSetDefault(@scr_original_handle)
ensure
@scr_handle = nil
@scr_original_handle = nil
end
end
end
end
17 changes: 17 additions & 0 deletions src/ruby/yast/rspec/shortcuts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require "rspec"
require "yast"

module Yast
module RSpec
# RSpec extension adding commodity shortcuts to enhance readability
module Shortcuts
# Shortcut for generating Yast::Path objects
#
# @param route [String] textual representation of the path
# @return [Yast::Path] the corresponding Path object
def path(route)
Yast::Path.new(route)
end
end
end
end
Empty file added tests/ruby/chroot/just_a_file
Empty file.
120 changes: 120 additions & 0 deletions tests/ruby/rspec_scr_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#!/usr/bin/env rspec

require_relative "test_helper"

require "yast/rspec"

describe Yast::RSpec::SCR do
let(:chroot) { File.join(File.dirname(__FILE__), "chroot") }

class DummyError < Exception; end

def root_content
Yast::SCR.Read(path(".target.dir"), "/")
end

describe "#change_scr_root" do
describe "file check" do
it "raises an exception if the directory does not exist" do
expect { change_scr_root("not/found/file") }.
to raise_exception(RuntimeError, /not a valid directory/)
end

it "raises an exception if called on a regular file" do
expect { change_scr_root(File.join(chroot, "just_a_file")) }.
to raise_exception(RuntimeError, /not a valid directory/)
end
end

describe "block syntax" do
it "changes the root path inside the block" do
expect(root_content).not_to eq(["just_a_file"])
change_scr_root(chroot) do
expect(root_content).to eq(["just_a_file"])
end
end

it "restores the original path after running the block" do
change_scr_root(chroot) do
# Do something in the chroot
end
expect(root_content).not_to eq(["just_a_file"])
end

it "restores the original path after a exception" do
begin
change_scr_root(chroot) do
raise DummyError
end
rescue DummyError
# Just catch the exception
end
expect(root_content).not_to eq(["just_a_file"])
end

it "raises an exception for nested calls" do
change_scr_root(chroot) do
expect { change_scr_root(chroot) }.
to raise_exception(RuntimeError, /reset_scr_root was expected/)
end
expect(root_content).not_to eq(["just_a_file"])
end
end

describe "usage with an around hook" do
around { |example| change_scr_root(chroot, &example) }

it "changes the root path within the example" do
expect(root_content).to eq(["just_a_file"])
end

it "raises an exception for nested calls" do
expect { change_scr_root(chroot) }.
to raise_exception(RuntimeError, /reset_scr_root was expected/)
end
end

describe "non-block syntax" do
after do
reset_scr_root
end

it "changes the root path" do
expect(root_content).not_to eq(["just_a_file"])
change_scr_root(chroot)
expect(root_content).to eq(["just_a_file"])
end

it "raises an exception for consecutive calls" do
change_scr_root(chroot)
expect { change_scr_root(chroot) }.
to raise_exception(RuntimeError, /reset_scr_root was expected/)
end
end
end

describe "#reset_scr_root" do
it "restores the original path" do
change_scr_root(chroot)
reset_scr_root
expect(root_content).not_to eq(["just_a_file"])
end

it "raises an exception if #change_scr_root was not called before" do
expect { reset_scr_root }.
to raise_exception(RuntimeError, /Unable to find a chrooted SCR/)
end

it "raises an exception if default SCR was modified" do
original_handle = Yast::WFM.SCRGetDefault
change_scr_root(chroot)

# Manually close the chroot
Yast::WFM.SCRClose(Yast::WFM.SCRGetDefault)
Yast::WFM.SCRSetDefault(original_handle)

expect { reset_scr_root }.
to raise_exception(RuntimeError, /not the current default/)
end
end
end
13 changes: 13 additions & 0 deletions tests/ruby/rspec_shortcuts_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env rspec

require_relative "test_helper"

require "yast/rspec"

describe Yast::RSpec::Shortcuts do
describe "#path" do
it "returns the expected Yast::Path object" do
expect(path(".target.dir")).to eq(Yast::Path.new(".target.dir"))
end
end
end

0 comments on commit 7deaa82

Please sign in to comment.