mvz-live_ast 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|