mvz-live_ast 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGES.rdoc +93 -0
- data/README.rdoc +419 -0
- data/Rakefile +21 -0
- data/devel/levitate.rb +853 -0
- data/devel/levitate_config.rb +4 -0
- data/lib/live_ast.rb +4 -0
- data/lib/live_ast/ast_eval.rb +11 -0
- data/lib/live_ast/ast_load.rb +15 -0
- data/lib/live_ast/base.rb +73 -0
- data/lib/live_ast/common.rb +48 -0
- data/lib/live_ast/error.rb +20 -0
- data/lib/live_ast/evaler.rb +32 -0
- data/lib/live_ast/full.rb +2 -0
- data/lib/live_ast/irb_spy.rb +43 -0
- data/lib/live_ast/linker.rb +122 -0
- data/lib/live_ast/loader.rb +60 -0
- data/lib/live_ast/reader.rb +26 -0
- data/lib/live_ast/replace_eval.rb +121 -0
- data/lib/live_ast/replace_load.rb +14 -0
- data/lib/live_ast/replace_raise.rb +18 -0
- data/lib/live_ast/ruby_parser.rb +36 -0
- data/lib/live_ast/ruby_parser/test.rb +197 -0
- data/lib/live_ast/ruby_parser/unparser.rb +13 -0
- data/lib/live_ast/to_ast.rb +26 -0
- data/lib/live_ast/to_ruby.rb +24 -0
- data/lib/live_ast/version.rb +3 -0
- data/test/ast_eval_feature_test.rb +11 -0
- data/test/ast_load_feature_test.rb +11 -0
- data/test/attr_test.rb +24 -0
- data/test/backtrace_test.rb +158 -0
- data/test/covert_define_method_test.rb +23 -0
- data/test/def_test.rb +35 -0
- data/test/define_method_test.rb +67 -0
- data/test/define_singleton_method_test.rb +15 -0
- data/test/encoding_test.rb +52 -0
- data/test/encoding_test/bad.rb +1 -0
- data/test/encoding_test/cp932.rb +6 -0
- data/test/encoding_test/default.rb +5 -0
- data/test/encoding_test/eucjp.rb +6 -0
- data/test/encoding_test/koi8.rb +6 -0
- data/test/encoding_test/koi8_shebang.rb +7 -0
- data/test/encoding_test/koi8_with_utf8bom.rb +6 -0
- data/test/encoding_test/usascii.rb +6 -0
- data/test/encoding_test/usascii_with_utf8bom.rb +6 -0
- data/test/encoding_test/utf8.rb +6 -0
- data/test/encoding_test/utf8bom.rb +6 -0
- data/test/encoding_test/utf8bom_only.rb +5 -0
- data/test/encoding_test/utf8dos.rb +6 -0
- data/test/encoding_test/utf8mac.rb +6 -0
- data/test/encoding_test/utf8mac_alt.rb +6 -0
- data/test/encoding_test/utf8unix.rb +6 -0
- data/test/error_test.rb +116 -0
- data/test/eval_test.rb +269 -0
- data/test/flush_cache_test.rb +98 -0
- data/test/irb_test.rb +25 -0
- data/test/lambda_test.rb +56 -0
- data/test/load_path_test.rb +78 -0
- data/test/load_test.rb +123 -0
- data/test/main.rb +140 -0
- data/test/nested_test.rb +29 -0
- data/test/noninvasive_test.rb +51 -0
- data/test/readme_test.rb +16 -0
- data/test/recursive_eval_test.rb +52 -0
- data/test/redefine_method_test.rb +83 -0
- data/test/reload_test.rb +105 -0
- data/test/replace_eval_test.rb +405 -0
- data/test/rubygems_test.rb +25 -0
- data/test/rubyspec_test.rb +39 -0
- data/test/singleton_test.rb +25 -0
- data/test/stdlib_test.rb +13 -0
- data/test/thread_test.rb +44 -0
- data/test/to_ast_feature_test.rb +15 -0
- data/test/to_ruby_feature_test.rb +15 -0
- data/test/to_ruby_test.rb +87 -0
- metadata +275 -0
data/test/nested_test.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative 'main'
|
2
|
+
|
3
|
+
class NestedTest < RegularTest
|
4
|
+
def test_lambda
|
5
|
+
a = lambda {
|
6
|
+
lambda {
|
7
|
+
"33"
|
8
|
+
}
|
9
|
+
}
|
10
|
+
|
11
|
+
assert_equal nested_lambdas("33"), a.to_ast
|
12
|
+
assert_equal no_arg_block(:lambda, "33"), a.call.to_ast
|
13
|
+
end
|
14
|
+
|
15
|
+
class A
|
16
|
+
def f
|
17
|
+
Class.new do
|
18
|
+
def g
|
19
|
+
"44"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_defs
|
26
|
+
assert_equal nested_defs(:f, :g, "44"), A.instance_method(:f).to_ast
|
27
|
+
assert_equal no_arg_def(:g, "44"), A.new.f.instance_method(:g).to_ast
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require_relative 'main'
|
2
|
+
|
3
|
+
class AAA_NoninvasiveTest < BaseTest
|
4
|
+
def test_no_clutter
|
5
|
+
[Method, UnboundMethod, Proc].each do |klass|
|
6
|
+
assert !klass.instance_methods.include?(:to_ast)
|
7
|
+
assert !klass.instance_methods.include?(:to_ruby)
|
8
|
+
end
|
9
|
+
|
10
|
+
assert !respond_to?(:ast_eval)
|
11
|
+
assert !Kernel.respond_to?(:ast_eval)
|
12
|
+
assert !respond_to?(:ast_load)
|
13
|
+
assert !Kernel.respond_to?(:ast_load)
|
14
|
+
end
|
15
|
+
|
16
|
+
DEFINE_A = lambda do
|
17
|
+
class A
|
18
|
+
def f
|
19
|
+
"A#f"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_method
|
25
|
+
DEFINE_A.call
|
26
|
+
|
27
|
+
expected = no_arg_def(:f, "A#f")
|
28
|
+
assert_equal expected, LiveAST.ast(A.instance_method(:f))
|
29
|
+
assert_equal expected, LiveAST.ast(A.new.method(:f))
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_lambda
|
33
|
+
a = lambda { |x, y| x ** y }
|
34
|
+
|
35
|
+
assert_equal binop_block(:lambda, :**), LiveAST.ast(a)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_ast_eval
|
39
|
+
code = %{ lambda { |x, y| x / y } }
|
40
|
+
|
41
|
+
expected = binop_block(:lambda, :/)
|
42
|
+
result = LiveAST.ast(LiveAST.eval(code, binding))
|
43
|
+
assert_equal expected, result
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_bogus
|
47
|
+
assert_raises TypeError do
|
48
|
+
LiveAST.ast(99)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/test/readme_test.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative 'main'
|
2
|
+
require_relative '../devel/levitate'
|
3
|
+
|
4
|
+
if LiveAST.parser::Test.respond_to?(:unified_sexp?) and
|
5
|
+
LiveAST.parser::Test.unified_sexp? and
|
6
|
+
RUBY_ENGINE != "jruby" then # jruby takes about a minute
|
7
|
+
sections = [
|
8
|
+
"Synopsis",
|
9
|
+
"+to_ruby+",
|
10
|
+
"Noninvasive Interface",
|
11
|
+
"Pure Ruby and +ast_eval+",
|
12
|
+
"Full Integration",
|
13
|
+
]
|
14
|
+
|
15
|
+
Levitate.doc_to_test("README.rdoc", *sections)
|
16
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative 'main'
|
2
|
+
|
3
|
+
class RecursiveEvalTest < RegularTest
|
4
|
+
DEFINE = lambda do
|
5
|
+
ast_eval %{
|
6
|
+
class A
|
7
|
+
ast_eval %{
|
8
|
+
def f
|
9
|
+
"A#f"
|
10
|
+
end
|
11
|
+
}, binding
|
12
|
+
|
13
|
+
ast_eval %{
|
14
|
+
ast_eval %{
|
15
|
+
remove_method :f
|
16
|
+
def f(x, y)
|
17
|
+
x + y
|
18
|
+
end
|
19
|
+
|
20
|
+
def g
|
21
|
+
"A#g"
|
22
|
+
end
|
23
|
+
}, binding
|
24
|
+
|
25
|
+
LAMBDA = ast_eval %{
|
26
|
+
lambda { |x, y| x * y }
|
27
|
+
}, binding
|
28
|
+
}, binding
|
29
|
+
end
|
30
|
+
}, binding
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_method
|
34
|
+
defined?(A) or DEFINE.call
|
35
|
+
assert_equal "#{self.class}::A", A.name
|
36
|
+
|
37
|
+
assert_equal binop_def(:f, :+),
|
38
|
+
A.instance_method(:f).to_ast
|
39
|
+
|
40
|
+
assert_equal no_arg_def(:g, "A#g"),
|
41
|
+
A.instance_method(:g).to_ast
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_lambda
|
45
|
+
defined?(A) or DEFINE.call
|
46
|
+
assert_equal "#{self.class}::A", A.name
|
47
|
+
|
48
|
+
assert_equal binop_block(:lambda, :*),
|
49
|
+
A::LAMBDA.to_ast
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require_relative 'main'
|
2
|
+
|
3
|
+
class RedefineMethodTest < RegularTest
|
4
|
+
DEFINE_A = lambda do
|
5
|
+
class A
|
6
|
+
def f
|
7
|
+
"old A#f"
|
8
|
+
end
|
9
|
+
|
10
|
+
PREVIOUS_Af = instance_method(:f)
|
11
|
+
remove_method :f
|
12
|
+
|
13
|
+
def f(x, y)
|
14
|
+
x * y
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_inclass_redef
|
20
|
+
DEFINE_A.call
|
21
|
+
|
22
|
+
assert_equal binop_def(:f, :*),
|
23
|
+
A.instance_method(:f).to_ast
|
24
|
+
|
25
|
+
assert_equal no_arg_def(:f, "old A#f"),
|
26
|
+
A::PREVIOUS_Af.to_ast
|
27
|
+
end
|
28
|
+
|
29
|
+
DEFINE_B = lambda do
|
30
|
+
class B
|
31
|
+
def f
|
32
|
+
"old B#f"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_dynamic_redef
|
38
|
+
DEFINE_B.call
|
39
|
+
|
40
|
+
assert_equal "old B#f", B.new.f
|
41
|
+
assert_equal no_arg_def(:f, "old B#f"), B.instance_method(:f).to_ast
|
42
|
+
|
43
|
+
B.class_eval do
|
44
|
+
remove_method :f
|
45
|
+
define_method :f do |x, y|
|
46
|
+
x - y
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
assert_equal 11, B.new.f(44, 33)
|
51
|
+
|
52
|
+
assert_equal binop_define_method(:f, :-),
|
53
|
+
B.instance_method(:f).to_ast
|
54
|
+
end
|
55
|
+
|
56
|
+
DEFINE_C = lambda do
|
57
|
+
class C
|
58
|
+
def f
|
59
|
+
"old C#f"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_dynamic_redef_with_eval
|
65
|
+
DEFINE_C.call
|
66
|
+
|
67
|
+
assert_equal "old C#f", C.new.f
|
68
|
+
|
69
|
+
C.class_eval do
|
70
|
+
ast_eval %{
|
71
|
+
remove_method :f
|
72
|
+
define_method :f do |x, y|
|
73
|
+
x * y
|
74
|
+
end
|
75
|
+
}, binding
|
76
|
+
end
|
77
|
+
|
78
|
+
assert_equal 12, C.new.f(3, 4)
|
79
|
+
|
80
|
+
assert_equal binop_define_method(:f, :*),
|
81
|
+
C.instance_method(:f).to_ast
|
82
|
+
end
|
83
|
+
end
|
data/test/reload_test.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
require_relative 'main'
|
2
|
+
|
3
|
+
class AAB_ReloadTest < BaseTest
|
4
|
+
include FileUtils
|
5
|
+
|
6
|
+
def test_reloading
|
7
|
+
raw_reload
|
8
|
+
require 'live_ast/ast_load'
|
9
|
+
noninvasive_ast_reload
|
10
|
+
require 'live_ast/replace_load'
|
11
|
+
ast_reload
|
12
|
+
end
|
13
|
+
|
14
|
+
def raw_reload
|
15
|
+
code_1 = %{
|
16
|
+
class AAB_ReloadTest::A
|
17
|
+
def f
|
18
|
+
"first A#f"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
}
|
22
|
+
|
23
|
+
code_2 = %{
|
24
|
+
class AAB_ReloadTest::A
|
25
|
+
def f
|
26
|
+
"second A#f"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
}
|
30
|
+
|
31
|
+
temp_file code_1 do |file|
|
32
|
+
load file
|
33
|
+
|
34
|
+
LiveAST.ast(A.instance_method(:f))
|
35
|
+
|
36
|
+
write_file file, code_2
|
37
|
+
load file
|
38
|
+
|
39
|
+
# forced a raw-reload inconsistency -- verify bogus
|
40
|
+
|
41
|
+
assert_equal no_arg_def(:f, "first A#f"),
|
42
|
+
LiveAST.ast(A.instance_method(:f))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def noninvasive_ast_reload
|
47
|
+
code_1 = %{
|
48
|
+
class AAB_ReloadTest::B
|
49
|
+
def f
|
50
|
+
"first B#f"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
}
|
54
|
+
|
55
|
+
code_2 = %{
|
56
|
+
class AAB_ReloadTest::B
|
57
|
+
def f
|
58
|
+
"second B#f"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
}
|
62
|
+
|
63
|
+
temp_file code_1 do |file|
|
64
|
+
load file
|
65
|
+
|
66
|
+
LiveAST.ast(B.instance_method(:f))
|
67
|
+
|
68
|
+
write_file file, code_2
|
69
|
+
ast_load file
|
70
|
+
|
71
|
+
assert_equal no_arg_def(:f, "second B#f"),
|
72
|
+
LiveAST.ast(B.instance_method(:f))
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def ast_reload
|
77
|
+
code_1 = %{
|
78
|
+
class AAB_ReloadTest::C
|
79
|
+
def f
|
80
|
+
"first C#f"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
}
|
84
|
+
|
85
|
+
code_2 = %{
|
86
|
+
class AAB_ReloadTest::C
|
87
|
+
def f
|
88
|
+
"second C#f"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
}
|
92
|
+
|
93
|
+
temp_file code_1 do |file|
|
94
|
+
load file
|
95
|
+
|
96
|
+
LiveAST.ast(C.instance_method(:f))
|
97
|
+
|
98
|
+
write_file file, code_2
|
99
|
+
load file
|
100
|
+
|
101
|
+
assert_equal no_arg_def(:f, "second C#f"),
|
102
|
+
LiveAST.ast(C.instance_method(:f))
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,405 @@
|
|
1
|
+
require_relative 'main'
|
2
|
+
|
3
|
+
class ZZY_ReplaceEvalTest < ReplaceEvalTest
|
4
|
+
RESULT = {}
|
5
|
+
|
6
|
+
def setup
|
7
|
+
RESULT.clear
|
8
|
+
end
|
9
|
+
|
10
|
+
DEFINE_A = lambda do
|
11
|
+
class A
|
12
|
+
eval %{
|
13
|
+
def f(x, y)
|
14
|
+
x**y
|
15
|
+
end
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_a_def_method
|
21
|
+
DEFINE_A.call
|
22
|
+
assert_equal binop_def(:f, :**), A.instance_method(:f).to_ast
|
23
|
+
end
|
24
|
+
|
25
|
+
DEFINE_B = lambda do
|
26
|
+
eval %{
|
27
|
+
class B
|
28
|
+
def f(x, y)
|
29
|
+
x / y
|
30
|
+
end
|
31
|
+
end
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_def_class
|
36
|
+
DEFINE_B.call
|
37
|
+
assert_equal "ZZY_ReplaceEvalTest::B", B.name
|
38
|
+
assert_equal binop_def(:f, :/), B.instance_method(:f).to_ast
|
39
|
+
end
|
40
|
+
|
41
|
+
def moo
|
42
|
+
a = 22
|
43
|
+
ignore(a)
|
44
|
+
binding
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_binding_eval
|
48
|
+
assert_equal 22, moo.eval("a")
|
49
|
+
assert_equal 22, moo.eval("lambda { a }").call
|
50
|
+
end
|
51
|
+
|
52
|
+
DEFINE_P = lambda do
|
53
|
+
class P
|
54
|
+
eval %{
|
55
|
+
def f
|
56
|
+
@x = 33
|
57
|
+
RESULT[:old] = live_ast_original_eval("@x")
|
58
|
+
RESULT[:new] = eval("@x")
|
59
|
+
end
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_const_lookup
|
65
|
+
DEFINE_P.call
|
66
|
+
P.new.f
|
67
|
+
|
68
|
+
assert_equal 33, RESULT[:old]
|
69
|
+
assert_equal 33, RESULT[:new]
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_const_lookup_2
|
73
|
+
Class.new do
|
74
|
+
eval %{
|
75
|
+
def f
|
76
|
+
@x = 44
|
77
|
+
RESULT[:old] = live_ast_original_eval("@x")
|
78
|
+
RESULT[:new] = eval("@x")
|
79
|
+
end
|
80
|
+
}
|
81
|
+
end.new.f
|
82
|
+
|
83
|
+
assert_equal 44, RESULT[:old]
|
84
|
+
assert_equal 44, RESULT[:new]
|
85
|
+
end
|
86
|
+
|
87
|
+
DEFINE_QS = lambda do
|
88
|
+
class Q
|
89
|
+
class R
|
90
|
+
eval %{
|
91
|
+
def f
|
92
|
+
RESULT[:qr] = 55
|
93
|
+
end
|
94
|
+
}
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
module S
|
99
|
+
class T
|
100
|
+
eval %{
|
101
|
+
def f
|
102
|
+
RESULT[:st] = 66
|
103
|
+
end
|
104
|
+
}
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_const_lookup_3
|
110
|
+
DEFINE_QS.call
|
111
|
+
Q::R.new.f
|
112
|
+
S::T.new.f
|
113
|
+
assert_equal 55, RESULT[:qr]
|
114
|
+
assert_equal 66, RESULT[:st]
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_eval_arg_error
|
118
|
+
[[], (1..5).to_a].each do |args|
|
119
|
+
orig = assert_raises ArgumentError do
|
120
|
+
live_ast_original_eval(*args)
|
121
|
+
end
|
122
|
+
live = assert_raises ArgumentError do
|
123
|
+
eval(*args)
|
124
|
+
end
|
125
|
+
assert_equal orig.message, live.message
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_singleton_eval_arg_error
|
130
|
+
[[], (1..5).to_a].each do |args|
|
131
|
+
orig = assert_raises ArgumentError do
|
132
|
+
Kernel.live_ast_original_singleton_eval(*args)
|
133
|
+
end
|
134
|
+
live = assert_raises ArgumentError do
|
135
|
+
Kernel.eval(*args)
|
136
|
+
end
|
137
|
+
assert_equal orig.message, live.message
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_instance_eval_arg_error_no_block
|
142
|
+
[[], ('a'..'z').to_a].each do |args|
|
143
|
+
orig = assert_raises ArgumentError do
|
144
|
+
Object.new.live_ast_original_instance_eval(*args)
|
145
|
+
end
|
146
|
+
live = assert_raises ArgumentError do
|
147
|
+
Object.new.instance_eval(*args)
|
148
|
+
end
|
149
|
+
assert_equal orig.message, live.message
|
150
|
+
end
|
151
|
+
|
152
|
+
orig = assert_raises TypeError do
|
153
|
+
Object.new.live_ast_original_instance_eval(nil)
|
154
|
+
end
|
155
|
+
live = assert_raises TypeError do
|
156
|
+
Object.new.instance_eval(nil)
|
157
|
+
end
|
158
|
+
assert_equal orig.message, live.message
|
159
|
+
|
160
|
+
[[nil], [Object.new], [3], [4,3,2], (1..10).to_a].each do |args|
|
161
|
+
orig = assert_raises TypeError do
|
162
|
+
Object.new.live_ast_original_instance_eval(*args)
|
163
|
+
end
|
164
|
+
live = assert_raises TypeError do
|
165
|
+
Object.new.instance_eval(*args)
|
166
|
+
end
|
167
|
+
assert_equal orig.message, live.message
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def test_instance_eval_arg_error_with_block
|
172
|
+
orig = assert_raises ArgumentError do
|
173
|
+
Object.new.live_ast_original_instance_eval(3,4,5) { }
|
174
|
+
end
|
175
|
+
live = assert_raises ArgumentError do
|
176
|
+
Object.new.instance_eval(3,4,5) { }
|
177
|
+
end
|
178
|
+
assert_equal orig.message, live.message
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_instance_eval_block
|
182
|
+
orig = {}
|
183
|
+
orig.live_ast_original_instance_eval do
|
184
|
+
self[:x] = 33
|
185
|
+
end
|
186
|
+
assert_equal 33, orig[:x]
|
187
|
+
|
188
|
+
live = {}
|
189
|
+
live.instance_eval do
|
190
|
+
self[:x] = 44
|
191
|
+
end
|
192
|
+
assert_equal 44, live[:x]
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_instance_eval_string
|
196
|
+
orig = {}
|
197
|
+
orig.live_ast_original_instance_eval %{
|
198
|
+
self[:x] = 33
|
199
|
+
}
|
200
|
+
assert_equal 33, orig[:x]
|
201
|
+
|
202
|
+
live = {}
|
203
|
+
live.instance_eval %{
|
204
|
+
self[:x] = 44
|
205
|
+
}
|
206
|
+
assert_equal 44, live[:x]
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_instance_eval_binding
|
210
|
+
x = 33
|
211
|
+
orig = {}
|
212
|
+
orig.live_ast_original_instance_eval %{
|
213
|
+
self[:x] = x
|
214
|
+
self[:f] = lambda { "f" }
|
215
|
+
}
|
216
|
+
assert_equal x, orig[:x]
|
217
|
+
|
218
|
+
y = 44
|
219
|
+
live = {}
|
220
|
+
live.instance_eval %{
|
221
|
+
self[:y] = y
|
222
|
+
self[:g] = lambda { "g" }
|
223
|
+
}
|
224
|
+
assert_equal y, live[:y]
|
225
|
+
|
226
|
+
assert_equal no_arg_block(:lambda, "g"), live[:g].to_ast
|
227
|
+
end
|
228
|
+
|
229
|
+
def test_module_eval_block
|
230
|
+
orig = Module.new
|
231
|
+
orig.live_ast_original_module_eval do
|
232
|
+
def f
|
233
|
+
"orig"
|
234
|
+
end
|
235
|
+
end
|
236
|
+
orig.instance_method(:f)
|
237
|
+
|
238
|
+
live = Module.new
|
239
|
+
live.module_eval do
|
240
|
+
def f
|
241
|
+
"live"
|
242
|
+
end
|
243
|
+
end
|
244
|
+
assert_equal no_arg_def(:f, "live"),
|
245
|
+
live.instance_method(:f).to_ast
|
246
|
+
end
|
247
|
+
|
248
|
+
def test_module_eval_string
|
249
|
+
orig = Module.new
|
250
|
+
orig.live_ast_original_module_eval %{
|
251
|
+
def f
|
252
|
+
"orig"
|
253
|
+
end
|
254
|
+
}
|
255
|
+
orig.instance_method(:f)
|
256
|
+
|
257
|
+
live = Module.new
|
258
|
+
live.module_eval %{
|
259
|
+
def h
|
260
|
+
"live h"
|
261
|
+
end
|
262
|
+
}
|
263
|
+
assert_equal no_arg_def(:h, "live h"),
|
264
|
+
live.instance_method(:h).to_ast
|
265
|
+
end
|
266
|
+
|
267
|
+
def test_module_eval_binding
|
268
|
+
x = 33
|
269
|
+
ignore(x)
|
270
|
+
orig = Class.new
|
271
|
+
orig.live_ast_original_module_eval %{
|
272
|
+
define_method :value do
|
273
|
+
x
|
274
|
+
end
|
275
|
+
define_method :f do
|
276
|
+
lambda { }
|
277
|
+
end
|
278
|
+
}
|
279
|
+
assert_equal 33, orig.new.value
|
280
|
+
assert orig.new.f.is_a?(Proc)
|
281
|
+
|
282
|
+
y = 44
|
283
|
+
ignore(y)
|
284
|
+
live = Class.new
|
285
|
+
live.module_eval %{
|
286
|
+
define_method :value do
|
287
|
+
y
|
288
|
+
end
|
289
|
+
define_method :g do
|
290
|
+
lambda { "g return" }
|
291
|
+
end
|
292
|
+
}
|
293
|
+
assert_equal 44, live.new.value
|
294
|
+
assert live.new.g.is_a?(Proc)
|
295
|
+
|
296
|
+
assert_equal no_arg_block(:lambda, "g return"),
|
297
|
+
live.new.g.to_ast
|
298
|
+
end
|
299
|
+
|
300
|
+
def test_module_eval_file_line
|
301
|
+
klass = Module.new
|
302
|
+
|
303
|
+
orig =
|
304
|
+
klass.live_ast_original_module_eval("[__FILE__, __LINE__]", "test", 102)
|
305
|
+
live =
|
306
|
+
klass.module_eval("[__FILE__, __LINE__]", "test", 102)
|
307
|
+
|
308
|
+
unfixable do
|
309
|
+
assert_equal orig, live
|
310
|
+
end
|
311
|
+
|
312
|
+
live.first.sub!(/#{Regexp.quote LiveAST::Linker::REVISION_TOKEN}.*\Z/, "")
|
313
|
+
assert_equal orig, live
|
314
|
+
assert_equal ["test", 102], live
|
315
|
+
end
|
316
|
+
|
317
|
+
def test_module_eval_to_str
|
318
|
+
file = MiniTest::Mock.new
|
319
|
+
file.expect(:to_str, "zebra.rb")
|
320
|
+
Class.new.module_eval("33 + 44", file)
|
321
|
+
file.verify
|
322
|
+
end
|
323
|
+
|
324
|
+
def test_eval_not_hosed
|
325
|
+
assert_equal 3, eval("1 + 2")
|
326
|
+
1.times do
|
327
|
+
assert_equal 3, eval("1 + 2")
|
328
|
+
end
|
329
|
+
|
330
|
+
assert_equal(3, eval(%{ eval("1 + 2") }))
|
331
|
+
1.times do
|
332
|
+
assert_equal(3, eval(%{ eval("1 + 2") }))
|
333
|
+
end
|
334
|
+
|
335
|
+
x = 5
|
336
|
+
eval %{
|
337
|
+
assert_equal(3, eval(%{ eval("1 + 2") }))
|
338
|
+
x = 6
|
339
|
+
}
|
340
|
+
assert_equal 6, x
|
341
|
+
end
|
342
|
+
|
343
|
+
def test_local_var_collision
|
344
|
+
args = 33
|
345
|
+
ignore(args)
|
346
|
+
|
347
|
+
assert_equal 33, live_ast_original_eval("args")
|
348
|
+
assert_equal 33, eval("args")
|
349
|
+
|
350
|
+
assert_equal 33, Kernel.live_ast_original_singleton_eval("args")
|
351
|
+
assert_equal 33, Kernel.eval("args")
|
352
|
+
|
353
|
+
assert_equal 33, binding.live_ast_original_binding_eval("args")
|
354
|
+
assert_equal 33, binding.eval("args")
|
355
|
+
|
356
|
+
assert_equal 33, Object.new.live_ast_original_instance_eval("args")
|
357
|
+
assert_equal 33, Object.new.instance_eval("args")
|
358
|
+
|
359
|
+
assert_equal 33, Class.new.live_ast_original_module_eval("args")
|
360
|
+
assert_equal 33, Class.new.module_eval("args")
|
361
|
+
|
362
|
+
assert_equal 33, Class.new.live_ast_original_instance_eval("args")
|
363
|
+
assert_equal 33, Class.new.instance_eval("args")
|
364
|
+
end
|
365
|
+
|
366
|
+
def test_location_without_binding
|
367
|
+
expected = ["(eval)", 2]
|
368
|
+
|
369
|
+
assert_equal expected, live_ast_original_eval("\n[__FILE__, __LINE__]")
|
370
|
+
|
371
|
+
unfixable do
|
372
|
+
assert_equal expected, eval("\n[__FILE__, __LINE__]")
|
373
|
+
end
|
374
|
+
|
375
|
+
file, line = eval("\n[__FILE__, __LINE__]")
|
376
|
+
file = LiveAST.strip_token file
|
377
|
+
|
378
|
+
assert_equal expected, [file, line]
|
379
|
+
end
|
380
|
+
|
381
|
+
DEFINE_BO_TEST = lambda do
|
382
|
+
class BasicObject
|
383
|
+
Kernel.eval("1 + 1")
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
def test_basic_object
|
388
|
+
::BasicObject.new.instance_eval %{
|
389
|
+
t = 33
|
390
|
+
::ZZY_ReplaceEvalTest::RESULT[:bo_test] = t + 44
|
391
|
+
}
|
392
|
+
assert_equal 77, RESULT[:bo_test]
|
393
|
+
end
|
394
|
+
|
395
|
+
class Z
|
396
|
+
def initialize
|
397
|
+
@t = 99
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
def test_instance_variables
|
402
|
+
assert_equal 99, Z.new.instance_eval{ @t }
|
403
|
+
assert_equal 99, Z.new.instance_eval("@t")
|
404
|
+
end
|
405
|
+
end
|