Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Be more picky about int/float arguments in Ruby #1596

Merged
merged 1 commit into from
Jun 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions fixtures/type-limits/tests/bindings/test_type_limits.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ def test_larger_numbers(self):
self.assertEqual(take_u64(10**19), 10**19)

def test_non_integer(self):
self.assertRaises(TypeError, lambda: take_i8(None))
self.assertRaises(TypeError, lambda: take_i16(None))
self.assertRaises(TypeError, lambda: take_i32(None))
self.assertRaises(TypeError, lambda: take_i64(None))
self.assertRaises(TypeError, lambda: take_u8(None))
self.assertRaises(TypeError, lambda: take_u16(None))
self.assertRaises(TypeError, lambda: take_u32(None))
self.assertRaises(TypeError, lambda: take_u64(None))

self.assertRaises(TypeError, lambda: take_i8("0"))
self.assertRaises(TypeError, lambda: take_i16("0"))
self.assertRaises(TypeError, lambda: take_i32("0"))
Expand Down Expand Up @@ -97,6 +106,15 @@ class A:
self.assertRaises(TypeError, lambda: take_u64(A()))

def test_integer_like(self):
self.assertEqual(take_i8(123), 123.0)
self.assertEqual(take_i16(123), 123.0)
self.assertEqual(take_i32(123), 123.0)
self.assertEqual(take_i64(123), 123.0)
self.assertEqual(take_u8(123), 123.0)
self.assertEqual(take_u16(123), 123.0)
self.assertEqual(take_u32(123), 123.0)
self.assertEqual(take_u64(123), 123.0)

self.assertEqual(take_i8(False), 0)
self.assertEqual(take_i16(False), 0)
self.assertEqual(take_i32(False), 0)
Expand Down Expand Up @@ -129,6 +147,9 @@ def __index__(self):
self.assertEqual(take_u64(A()), 123)

def test_non_float(self):
self.assertRaises(TypeError, lambda: take_f32(None))
self.assertRaises(TypeError, lambda: take_f64(None))

self.assertRaises(TypeError, lambda: take_f32("0"))
self.assertRaises(TypeError, lambda: take_f64("0"))

Expand Down
149 changes: 149 additions & 0 deletions fixtures/type-limits/tests/bindings/test_type_limits.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,155 @@ def test_larger_numbers
assert_equal(UniffiTypeLimits.take_u16(10**4), 10**4)
assert_equal(UniffiTypeLimits.take_u32(10**9), 10**9)
assert_equal(UniffiTypeLimits.take_u64(10**19), 10**19)

assert_raise FloatDomainError do UniffiTypeLimits.take_i8(-Float::INFINITY) end
assert_raise FloatDomainError do UniffiTypeLimits.take_i16(-Float::INFINITY) end
assert_raise FloatDomainError do UniffiTypeLimits.take_i32(-Float::INFINITY) end
assert_raise FloatDomainError do UniffiTypeLimits.take_i64(-Float::INFINITY) end
assert_raise FloatDomainError do UniffiTypeLimits.take_u8(-Float::INFINITY) end
assert_raise FloatDomainError do UniffiTypeLimits.take_u16(-Float::INFINITY) end
assert_raise FloatDomainError do UniffiTypeLimits.take_u32(-Float::INFINITY) end
assert_raise FloatDomainError do UniffiTypeLimits.take_u64(-Float::INFINITY) end

assert_raise FloatDomainError do UniffiTypeLimits.take_i8(Float::INFINITY) end
assert_raise FloatDomainError do UniffiTypeLimits.take_i16(Float::INFINITY) end
assert_raise FloatDomainError do UniffiTypeLimits.take_i32(Float::INFINITY) end
assert_raise FloatDomainError do UniffiTypeLimits.take_i64(Float::INFINITY) end
assert_raise FloatDomainError do UniffiTypeLimits.take_u8(Float::INFINITY) end
assert_raise FloatDomainError do UniffiTypeLimits.take_u16(Float::INFINITY) end
assert_raise FloatDomainError do UniffiTypeLimits.take_u32(Float::INFINITY) end
assert_raise FloatDomainError do UniffiTypeLimits.take_u64(Float::INFINITY) end

assert_raise FloatDomainError do UniffiTypeLimits.take_i8(Float::NAN) end
assert_raise FloatDomainError do UniffiTypeLimits.take_i16(Float::NAN) end
assert_raise FloatDomainError do UniffiTypeLimits.take_i32(Float::NAN) end
assert_raise FloatDomainError do UniffiTypeLimits.take_i64(Float::NAN) end
assert_raise FloatDomainError do UniffiTypeLimits.take_u8(Float::NAN) end
assert_raise FloatDomainError do UniffiTypeLimits.take_u16(Float::NAN) end
assert_raise FloatDomainError do UniffiTypeLimits.take_u32(Float::NAN) end
assert_raise FloatDomainError do UniffiTypeLimits.take_u64(Float::NAN) end
end
class NonInteger
end
def test_non_integer
assert_raise TypeError do UniffiTypeLimits.take_i8(nil) end
assert_raise TypeError do UniffiTypeLimits.take_i16(nil) end
assert_raise TypeError do UniffiTypeLimits.take_i32(nil) end
assert_raise TypeError do UniffiTypeLimits.take_i64(nil) end
assert_raise TypeError do UniffiTypeLimits.take_u8(nil) end
assert_raise TypeError do UniffiTypeLimits.take_u16(nil) end
assert_raise TypeError do UniffiTypeLimits.take_u32(nil) end
assert_raise TypeError do UniffiTypeLimits.take_u64(nil) end

assert_raise TypeError do UniffiTypeLimits.take_i8("0") end
assert_raise TypeError do UniffiTypeLimits.take_i16("0") end
assert_raise TypeError do UniffiTypeLimits.take_i32("0") end
assert_raise TypeError do UniffiTypeLimits.take_i64("0") end
assert_raise TypeError do UniffiTypeLimits.take_u8("0") end
assert_raise TypeError do UniffiTypeLimits.take_u16("0") end
assert_raise TypeError do UniffiTypeLimits.take_u32("0") end
assert_raise TypeError do UniffiTypeLimits.take_u64("0") end

assert_raise TypeError do UniffiTypeLimits.take_i8(false) end
assert_raise TypeError do UniffiTypeLimits.take_i16(false) end
assert_raise TypeError do UniffiTypeLimits.take_i32(false) end
assert_raise TypeError do UniffiTypeLimits.take_i64(false) end
assert_raise TypeError do UniffiTypeLimits.take_u8(false) end
assert_raise TypeError do UniffiTypeLimits.take_u16(false) end
assert_raise TypeError do UniffiTypeLimits.take_u32(false) end
assert_raise TypeError do UniffiTypeLimits.take_u64(false) end

assert_raise TypeError do UniffiTypeLimits.take_i8(true) end
assert_raise TypeError do UniffiTypeLimits.take_i16(true) end
assert_raise TypeError do UniffiTypeLimits.take_i32(true) end
assert_raise TypeError do UniffiTypeLimits.take_i64(true) end
assert_raise TypeError do UniffiTypeLimits.take_u8(true) end
assert_raise TypeError do UniffiTypeLimits.take_u16(true) end
assert_raise TypeError do UniffiTypeLimits.take_u32(true) end
assert_raise TypeError do UniffiTypeLimits.take_u64(true) end

assert_raise TypeError do UniffiTypeLimits.take_i8(NonInteger.new) end
assert_raise TypeError do UniffiTypeLimits.take_i16(NonInteger.new) end
assert_raise TypeError do UniffiTypeLimits.take_i32(NonInteger.new) end
assert_raise TypeError do UniffiTypeLimits.take_i64(NonInteger.new) end
assert_raise TypeError do UniffiTypeLimits.take_u8(NonInteger.new) end
assert_raise TypeError do UniffiTypeLimits.take_u16(NonInteger.new) end
assert_raise TypeError do UniffiTypeLimits.take_u32(NonInteger.new) end
assert_raise TypeError do UniffiTypeLimits.take_u64(NonInteger.new) end
end
class IntegerLike
def to_int
123
end
end
def test_integer_like
assert_equal(UniffiTypeLimits.take_i8(123.0), 123)
assert_equal(UniffiTypeLimits.take_i16(123.0), 123)
assert_equal(UniffiTypeLimits.take_i32(123.0), 123)
assert_equal(UniffiTypeLimits.take_i64(123.0), 123)
assert_equal(UniffiTypeLimits.take_u8(123.0), 123)
assert_equal(UniffiTypeLimits.take_u16(123.0), 123)
assert_equal(UniffiTypeLimits.take_u32(123.0), 123)
assert_equal(UniffiTypeLimits.take_u64(123.0), 123)

assert_equal(UniffiTypeLimits.take_i8(-0.5), 0)
assert_equal(UniffiTypeLimits.take_i16(-0.5), 0)
assert_equal(UniffiTypeLimits.take_i32(-0.5), 0)
assert_equal(UniffiTypeLimits.take_i64(-0.5), 0)
assert_equal(UniffiTypeLimits.take_u8(-0.5), 0)
assert_equal(UniffiTypeLimits.take_u16(-0.5), 0)
assert_equal(UniffiTypeLimits.take_u32(-0.5), 0)
assert_equal(UniffiTypeLimits.take_u64(-0.5), 0)

assert_equal(UniffiTypeLimits.take_i8(IntegerLike.new), 123)
assert_equal(UniffiTypeLimits.take_i16(IntegerLike.new), 123)
assert_equal(UniffiTypeLimits.take_i32(IntegerLike.new), 123)
assert_equal(UniffiTypeLimits.take_i64(IntegerLike.new), 123)
assert_equal(UniffiTypeLimits.take_u8(IntegerLike.new), 123)
assert_equal(UniffiTypeLimits.take_u16(IntegerLike.new), 123)
assert_equal(UniffiTypeLimits.take_u32(IntegerLike.new), 123)
assert_equal(UniffiTypeLimits.take_u64(IntegerLike.new), 123)
end
class NonFloat
end
def test_non_float
assert_raise TypeError do UniffiTypeLimits.take_f32(nil) end
assert_raise TypeError do UniffiTypeLimits.take_f64(nil) end

assert_raise TypeError do UniffiTypeLimits.take_f32("0") end
assert_raise TypeError do UniffiTypeLimits.take_f64("0") end

assert_raise TypeError do UniffiTypeLimits.take_f32(false) end
assert_raise TypeError do UniffiTypeLimits.take_f64(false) end

assert_raise TypeError do UniffiTypeLimits.take_f32(true) end
assert_raise TypeError do UniffiTypeLimits.take_f64(true) end

assert_raise RangeError do UniffiTypeLimits.take_f32(1i) end
assert_raise RangeError do UniffiTypeLimits.take_f64(1i) end

assert_raise TypeError do UniffiTypeLimits.take_f32(NonFloat.new) end
assert_raise TypeError do UniffiTypeLimits.take_f64(NonFloat.new) end
end
def test_float_like
assert_equal(UniffiTypeLimits.take_f32(456), 456.0)
assert_equal(UniffiTypeLimits.take_f64(456), 456.0)
end
def test_special_floats
assert_equal(UniffiTypeLimits.take_f32(Float::INFINITY), Float::INFINITY)
assert_equal(UniffiTypeLimits.take_f64(Float::INFINITY), Float::INFINITY)

assert_equal(UniffiTypeLimits.take_f32(-Float::INFINITY), -Float::INFINITY)
assert_equal(UniffiTypeLimits.take_f64(-Float::INFINITY), -Float::INFINITY)

assert_equal(UniffiTypeLimits.take_f32(0.0).to_s, "0.0")
assert_equal(UniffiTypeLimits.take_f64(0.0).to_s, "0.0")

assert_equal(UniffiTypeLimits.take_f32(-0.0).to_s, "-0.0")
assert_equal(UniffiTypeLimits.take_f64(-0.0).to_s, "-0.0")

assert(UniffiTypeLimits.take_f32(Float::NAN).nan?)
assert(UniffiTypeLimits.take_f64(Float::NAN).nan?)
end
def test_strings
assert_raise Encoding::InvalidByteSequenceError do UniffiTypeLimits.take_string("\xff") end # invalid byte
Expand Down
2 changes: 1 addition & 1 deletion uniffi_bindgen/src/bindings/ruby/gen_ruby/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ mod filters {
Type::UInt16 => format!("{ns}::uniffi_in_range({nm}, \"u16\", 0, 2**16)"),
Type::UInt32 => format!("{ns}::uniffi_in_range({nm}, \"u32\", 0, 2**32)"),
Type::UInt64 => format!("{ns}::uniffi_in_range({nm}, \"u64\", 0, 2**64)"),
Type::Float32 | Type::Float64 => format!("{nm}.to_f"),
Type::Float32 | Type::Float64 => nm.to_string(),
Type::Boolean => format!("{nm} ? true : false"),
Type::Object { .. } | Type::Enum(_) | Type::Record(_) => nm.to_string(),
Type::String | Type::Bytes => format!("{ns}::uniffi_utf8({nm})"),
Expand Down
5 changes: 3 additions & 2 deletions uniffi_bindgen/src/bindings/ruby/templates/Helpers.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
def self.uniffi_in_range(i, type_name, min, max)
i = i.to_i
raise TypeError, "no implicit conversion of #{i} into Integer" unless i.respond_to?(:to_int)
i = i.to_int
raise RangeError, "#{type_name} requires #{min} <= value < #{max}" unless (min <= i && i < max)
i
end

def self.uniffi_utf8(v)
v = v.to_s.encode(Encoding::UTF_8)
v = v.to_str.encode(Encoding::UTF_8)
raise Encoding::InvalidByteSequenceError, "not a valid UTF-8 encoded string" unless v.valid_encoding?
v
end