Skip to content

Commit 8edcea7

Browse files
committed
Binding assertions
1 parent 4ce9460 commit 8edcea7

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

lib/literal.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,48 @@ module Literal
1919
loader.setup
2020
end
2121

22+
CLASS_METHOD = Kernel.instance_method(:class)
23+
CLASS_VARIABLE_GET_METHOD = Module.instance_method(:class_variable_get)
24+
INSTANCE_VARIABLE_GET_METHOD = Kernel.instance_method(:instance_variable_get)
25+
26+
module BindingAssert
27+
def assert(**kwargs)
28+
kwargs.each do |name, type|
29+
string_name = (Symbol === name) ? name.name : name
30+
first_byte = string_name.getbyte(0)
31+
32+
if first_byte == 64 # @foo
33+
if string_name.getbyte(1) == 64 # @@foo
34+
value = CLASS_VARIABLE_GET_METHOD.bind_call(
35+
CLASS_METHOD.bind_call(receiver), name
36+
)
37+
else # @foo
38+
value = INSTANCE_VARIABLE_GET_METHOD.bind_call(receiver, name)
39+
end
40+
elsif first_byte == 36 # $foo
41+
raise if string_name.match?(/[\s\.]/)
42+
value = eval(string_name)
43+
else # foo
44+
value = local_variable_get(name)
45+
end
46+
47+
unless type === value
48+
raise ::TypeError.new(<<~MESSAGE)
49+
Assertion failed!
50+
51+
#{name}
52+
Expected: #{type.inspect}
53+
Actual (#{value.class}): #{value.inspect}
54+
MESSAGE
55+
end
56+
end
57+
end
58+
end
59+
60+
::Binding.include(Literal::BindingAssert)
61+
62+
63+
2264
def self.Value(*args, **kwargs, &block)
2365
value_class = Class.new(Literal::Value)
2466

test/assert.test.rb

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
$a = 1
2+
3+
test "assert with local variable" do
4+
refute_raises do
5+
a = 1
6+
b = "Hello"
7+
8+
binding.assert(a: Integer, b: String)
9+
binding.assert("a" => Integer, "b" => String)
10+
end
11+
12+
assert_raises Literal::TypeError do
13+
a = 1
14+
binding.assert(a: String)
15+
end
16+
end
17+
18+
test "assert with global variable" do
19+
refute_raises do
20+
binding.assert("$a": Integer)
21+
end
22+
23+
assert_raises Literal::TypeError do
24+
binding.assert("$a": String)
25+
end
26+
end
27+
28+
test "assert with instance variable" do
29+
refute_raises do
30+
@a = 1
31+
binding.assert("@a": Integer)
32+
end
33+
34+
assert_raises Literal::TypeError do
35+
@a = 1
36+
binding.assert("@a": String)
37+
end
38+
end
39+
40+
test "assert with class variable" do
41+
refute_raises do
42+
@@a = 1
43+
binding.assert("@@a": Integer)
44+
end
45+
46+
assert_raises Literal::TypeError do
47+
@@a = 1
48+
binding.assert("@@a": String)
49+
end
50+
end

0 commit comments

Comments
 (0)