Skip to content

Commit

Permalink
Merge branch 'master' into rubocop
Browse files Browse the repository at this point in the history
Conflicts:
	src/ruby/yast/logger.rb
	tests/ruby/builtins_spec.rb

Basically reran rubocop -a
  • Loading branch information
mvidner committed Jul 14, 2015
2 parents 81f3f9d + aaa39f8 commit db0c5d3
Show file tree
Hide file tree
Showing 13 changed files with 1,222 additions and 817 deletions.
14 changes: 14 additions & 0 deletions package/yast2-ruby-bindings.changes
@@ -1,3 +1,17 @@
-------------------------------------------------------------------
Mon Jun 29 07:59:11 UTC 2015 - ancor@suse.com

- Added Yast::Builtins::strftime with full i18n support
(part of fate#318486)
- 3.1.38

-------------------------------------------------------------------
Thu Jun 25 06:31:50 UTC 2015 - jreidinger@suse.com

- pass method name to logger (helps with debugging,
e.g. bnc#922308)
- 3.1.37

-------------------------------------------------------------------
Thu Jun 18 11:41:32 UTC 2015 - ancor@suse.com

Expand Down
2 changes: 1 addition & 1 deletion package/yast2-ruby-bindings.spec
Expand Up @@ -17,7 +17,7 @@


Name: yast2-ruby-bindings
Version: 3.1.36
Version: 3.1.38
Url: https://github.com/yast/yast-ruby-bindings
Release: 0
BuildRoot: %{_tmppath}/%{name}-%{version}-build
Expand Down
48 changes: 48 additions & 0 deletions src/binary/Builtin.cc
Expand Up @@ -632,6 +632,53 @@ extern "C" {
return INT2FIX(strcoll(RSTRING_PTR(str1), RSTRING_PTR(str2)));
}

// reads the value of a hash key
// used internally by stftime_wrapper
static int
tm_hash_value(VALUE hash, const char *key)
{
return NUM2INT(rb_hash_aref(hash, ID2SYM(rb_intern(key))));
}

// converts a hash to a tm structure
// used internally by stftime_wrapper
void
hash_to_tm(VALUE hash, struct tm *res)
{
res->tm_sec = tm_hash_value(hash, "tm_sec");
res->tm_min = tm_hash_value(hash, "tm_min");
res->tm_hour = tm_hash_value(hash, "tm_hour");
res->tm_mday = tm_hash_value(hash, "tm_mday");
res->tm_mon = tm_hash_value(hash, "tm_mon");
res->tm_year = tm_hash_value(hash, "tm_year");
res->tm_wday = tm_hash_value(hash, "tm_wday");
res->tm_yday = tm_hash_value(hash, "tm_yday");
res->tm_isdst = tm_hash_value(hash, "tm_isdst");
}

#define STRFTIME_MAX_LENGTH 256
// a wrapper around strftime() function,
// needed for formatting using the current locale
static VALUE
strftime_wrapper(VALUE self, VALUE time, VALUE format)
{
char res[STRFTIME_MAX_LENGTH];
struct tm timeinfo;

Check_Type(format, T_STRING);
memset(&timeinfo, 0, sizeof timeinfo);
hash_to_tm(time, &timeinfo);

// Since std::put_time is not implemented in GCC4.9, we'll use
// setlocale and strftime instead of facets
setlocale(LC_TIME,""); // Needed to allow locale change at runtime
if (strftime(res, sizeof(res), RSTRING_PTR(format), &timeinfo)) {
return yrb_utf8_str_new(string(res));
} else {
rb_raise(rb_eRuntimeError, "The result of strftime would be longer than %d characters", STRFTIME_MAX_LENGTH);
return Qnil;
}
}
}

extern "C"
Expand Down Expand Up @@ -666,5 +713,6 @@ extern "C"
rb_define_singleton_method( rb_mBuiltins, "regexppos", RUBY_METHOD_FUNC(regexppos), 2);
rb_define_singleton_method( rb_mBuiltins, "regexpsub", RUBY_METHOD_FUNC(regexpsub), 3);
rb_define_singleton_method( rb_mBuiltins, "regexptokenize", RUBY_METHOD_FUNC(regexptokenize), 2);
rb_define_singleton_method( rb_mBuiltins, "strftime_wrapper", RUBY_METHOD_FUNC(strftime_wrapper), 2);
}
}
44 changes: 44 additions & 0 deletions src/ruby/yast/builtins.rb
Expand Up @@ -672,6 +672,50 @@ def self.y2usernote(*_args)
nil
end

# Wrapper for the C++ version of strftime. Needed because it honors the
# system locale settings, something that is not granted by the Ruby version
# of strftime.
# @see http://www.cplusplus.com/reference/ctime/strftime/
# @param time [Time/DateTime] time to format
# @param format [String] format string according to C++ strftime
# specification
# @return [String] formatted string
def self.strftime(time, format)
strftime_wrapper(time_to_tm(time), format)
end

# Creates a hash with the same fields that the C++ time structure.
# @private used internally by .strftime
# @see http://www.cplusplus.com/reference/ctime/tm/
# @param time [Time/DateTime] time to convert
# @return [Hash] hash with symbols as keys
def self.time_to_tm(time)
begin
tm = {
tm_sec: time.sec,
tm_min: time.min,
tm_hour: time.hour,
tm_mday: time.mday,
tm_mon: time.mon - 1, # January is 0 in C++
tm_year: time.year - 1900, # Another C++ peculiarity
tm_wday: time.wday,
tm_yday: time.yday - 1 # January 1st is 0 in C++
}
rescue NoMethodError
raise ArgumentError, "This doesn't look like a valid time: #{time}"
end
# tm_isdst > 0 -> in effect
# tm_isdst = 0 -> not in effect
# tm_isdst < 0 -> unknown
if time.respond_to?(:isdst)
tm[:tm_isdst] = time.isdst ? 1 : 0
else
tm[:tm_isdst] = -1
end
tm
end
private_class_method :time_to_tm

###########################################################
# Yast Path Builtins
###########################################################
Expand Down
2 changes: 1 addition & 1 deletion src/ruby/yast/logger.rb
Expand Up @@ -22,7 +22,7 @@ def y2_logger_helper(level, args)
res = Builtins.sformat(*args)
res.gsub!(/%/, "%%") # reescape all %
caller[caller_frame] =~ /(.+):(\d+):in `([^']+)'/
y2_logger(level, "Ruby", Regexp.last_match(1), Regexp.last_match(2).to_i, "", res)
y2_logger(level, "Ruby", Regexp.last_match(1), Regexp.last_match(2).to_i, Regexp.last_match(3), res)

if backtrace
y2_logger_helper(level, [2, "------------- Backtrace begin -------------"])
Expand Down
File renamed without changes.
163 changes: 163 additions & 0 deletions tests/ruby/builtins_casts_spec.rb
@@ -0,0 +1,163 @@
#!/usr/bin/env rspec
# encoding: utf-8

# FIXME: this file was autoconverted from test/unit syntax without
# adjusting it to good RSpec style (http://betterspecs.org/).
# Please improve it whenever adding examples.

require_relative "test_helper"

require "yast/builtins"
require "yast/path"
require "yast/term"

describe "Yast::Builtins type casting methods" do
describe ".toset" do
it "works as expected" do
expect(Yast::Builtins.toset(nil)).to eq(nil)

expect(Yast::Builtins.toset([])).to eq([])
expect(Yast::Builtins.toset(["A"])).to eq(["A"])
expect(Yast::Builtins.toset(["Z", "A"])).to eq(["A", "Z"])
expect(Yast::Builtins.toset([3, 2, 2, 1, 2, 1, 3, 1, 3, 3])).to eq([1, 2, 3])

expect(Yast::Builtins.toset([1, 5, 3, 2, 3, true, false, true])).to eq([false, true, 1, 2, 3, 5])
end
end

describe ".tostring" do
TOSTRING_TEST_DATA = [
[nil, "nil"],
[true, "true"],
[false, "false"],
["test", "test"],
[:test, "`test"],
[1, "1"],
[1.453, "1.453"],
[["test", :lest], '["test", `lest]'],
[Yast::Path.new(".etc.syconfig.\"-arg\""), ".etc.syconfig.\"-arg\""],
[Yast::Term.new(:id, ["test", :lest]), "`id ([\"test\", `lest])"],
[{ test: "data" }, "$[`test:\"data\"]"]
]

it "works as expected" do
TOSTRING_TEST_DATA.each do |input, result|
expect(Yast::Builtins.tostring(input)).to eq(result)
end
end

it "honors precision" do
expect(Yast::Builtins.tostring(1.453, 1)).to eq("1.5")
end
end

describe ".tohexstring" do
it "works as expected" do
expect(Yast::Builtins.tohexstring(nil)).to eq(nil)
expect(Yast::Builtins.tohexstring(nil, nil)).to eq(nil)
expect(Yast::Builtins.tohexstring(0)).to eq("0x0")
expect(Yast::Builtins.tohexstring(10)).to eq("0xa")
expect(Yast::Builtins.tohexstring(255)).to eq("0xff")
expect(Yast::Builtins.tohexstring(222_222)).to eq("0x3640e")

expect(Yast::Builtins.tohexstring(31, 0)).to eq("0x1f")
expect(Yast::Builtins.tohexstring(31, 1)).to eq("0x1f")
expect(Yast::Builtins.tohexstring(31, 4)).to eq("0x001f")
expect(Yast::Builtins.tohexstring(31, 6)).to eq("0x00001f")

expect(Yast::Builtins.tohexstring(31, -1)).to eq("0x1f")
expect(Yast::Builtins.tohexstring(31, -3)).to eq("0x1f ")

expect(Yast::Builtins.tohexstring(-3)).to eq("0xfffffffffffffffd")
expect(Yast::Builtins.tohexstring(-3, 5)).to eq("0xfffffffffffffffd")
expect(Yast::Builtins.tohexstring(-3, 18)).to eq("0x00fffffffffffffffd")
expect(Yast::Builtins.tohexstring(-3, 22)).to eq("0x000000fffffffffffffffd")

expect(Yast::Builtins.tohexstring(-3, -16)).to eq("0xfffffffffffffffd")
expect(Yast::Builtins.tohexstring(-3, -17)).to eq("0xfffffffffffffffd ")
expect(Yast::Builtins.tohexstring(-3, -22)).to eq("0xfffffffffffffffd ")
end
end

describe ".tointeger" do
it "works as expected" do
expect(Yast::Builtins.tointeger(nil)).to eq(nil)
expect(Yast::Builtins.tointeger("")).to eq(nil)
expect(Yast::Builtins.tointeger("foo")).to eq(nil)
expect(Yast::Builtins.tointeger(120)).to eq(120)
expect(Yast::Builtins.tointeger("120")).to eq(120)
expect(Yast::Builtins.tointeger(" 120asdf")).to eq(120)
expect(Yast::Builtins.tointeger(120.0)).to eq(120)
expect(Yast::Builtins.tointeger("0x20")).to eq(32)
expect(Yast::Builtins.tointeger(" 0x20")).to eq(0)
expect(Yast::Builtins.tointeger("0x20Z")).to eq(32)
expect(Yast::Builtins.tointeger("010")).to eq(8)
expect(Yast::Builtins.tointeger("-10")).to eq(-10)

# weird Yast cases
expect(Yast::Builtins.tointeger("-0x20")).to eq(0)
expect(Yast::Builtins.tointeger(" 0x20")).to eq(0)
expect(Yast::Builtins.tointeger(" 020")).to eq(20)
expect(Yast::Builtins.tointeger("-020")).to eq(-20)
expect(Yast::Builtins.tointeger("-0020")).to eq(-20)
end
end

describe ".tofloat" do
TOFLOAT_TESTDATA = [
[1, 1.0],
[nil, nil],
["42", 42.0],
["89.3", 89.3],
["test", 0.0],
[:test, nil]
]

it "works as expected" do
TOFLOAT_TESTDATA.each do |value, result|
expect(Yast::Builtins.tofloat(value)).to eq(result)
end
end
end

describe ".topath" do
it "works as expected" do
expect(Yast::Builtins.topath(nil)).to eq(nil)

expect(Yast::Builtins.topath(Yast::Path.new(".etc"))).to eq(Yast::Path.new(".etc"))

expect(Yast::Builtins.topath(".etc")).to eq(Yast::Path.new(".etc"))

expect(Yast::Builtins.topath("etc")).to eq(Yast::Path.new(".etc"))
end
end

describe "Float.tolstring" do
it "works as expected" do
old_lang = ENV["LANG"]
lc_all = ENV["LC_ALL"]
ENV["LANG"] = "cs_CZ.utf-8"
ENV["LC_ALL"] = "cs_CZ.utf-8"
ret = Yast::Builtins::Float.tolstring(0.52, 1)
expect(ret).to eq("0,5")
expect(ret.encoding).to eq(Encoding::UTF_8)
ENV["LANG"] = old_lang
ENV["LC_ALL"] = lc_all
end
end

describe "toterm" do
TOTERM_TEST_DATA = [
["test", Yast::Term.new(:test)],
[:test, Yast::Term.new(:test)],
[[:test, [:lest, :srst]], Yast::Term.new(:test, :lest, :srst)],
[[Yast::Term.new(:test)], Yast::Term.new(:test)]
]

it "works as expected" do
TOTERM_TEST_DATA.each do |input, res|
expect(Yast::Builtins.toterm(*input)).to eq(res)
end
end
end
end
62 changes: 62 additions & 0 deletions tests/ruby/builtins_float_spec.rb
@@ -0,0 +1,62 @@
#!/usr/bin/env rspec
# encoding: utf-8

# FIXME: this file was autoconverted from test/unit syntax without
# adjusting it to good RSpec style (http://betterspecs.org/).
# Please improve it whenever adding examples.

require_relative "test_helper"

require "yast/builtins"

describe Yast::Builtins::Float do
describe ".abs" do
it "works as expected" do
expect(Yast::Builtins::Float.abs(nil)).to eq(nil)

expect(Yast::Builtins::Float.abs(-5.4)).to eq(5.4)
end
end

describe ".ceil" do
it "works as expected" do
expect(Yast::Builtins::Float.ceil(nil)).to eq(nil)

expect(Yast::Builtins::Float.ceil(-5.4)).to eq(-5.0)

expect(Yast::Builtins::Float.ceil(5.4)).to eq(6.0)
expect(Yast::Builtins::Float.ceil(5.4).class).to eq(Float)
end
end

describe ".floor" do
it "works as expected" do
expect(Yast::Builtins::Float.floor(nil)).to eq(nil)

expect(Yast::Builtins::Float.floor(-5.4)).to eq(-6.0)

expect(Yast::Builtins::Float.floor(5.4)).to eq(5.0)
expect(Yast::Builtins::Float.floor(5.4).class).to eq(Float)
end
end

describe ".pow" do
it "works as expected" do
expect(Yast::Builtins::Float.pow(nil, 10.0)).to eq(nil)

expect(Yast::Builtins::Float.pow(10.0, 3.0)).to eq(1000.0)
expect(Yast::Builtins::Float.pow(10.0, 3.0).class).to eq(Float)
end
end

describe ".trunc" do
it "works as expected" do
expect(Yast::Builtins::Float.trunc(nil)).to eq(nil)

expect(Yast::Builtins::Float.trunc(-5.4)).to eq(-5.0)

expect(Yast::Builtins::Float.trunc(5.6)).to eq(5.0)
expect(Yast::Builtins::Float.trunc(5.4).class).to eq(Float)
end
end
end

0 comments on commit db0c5d3

Please sign in to comment.