live_ast 0.2.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.
- data/CHANGES.rdoc +6 -0
- data/MANIFEST +54 -0
- data/README.rdoc +388 -0
- data/Rakefile +19 -0
- data/devel/jumpstart.rb +983 -0
- data/lib/live_ast/ast_eval.rb +13 -0
- data/lib/live_ast/ast_load.rb +15 -0
- data/lib/live_ast/base.rb +56 -0
- data/lib/live_ast/cache.rb +14 -0
- data/lib/live_ast/error.rb +30 -0
- data/lib/live_ast/evaler.rb +66 -0
- data/lib/live_ast/linker.rb +107 -0
- data/lib/live_ast/loader.rb +69 -0
- data/lib/live_ast/parser.rb +48 -0
- data/lib/live_ast/replace_load.rb +14 -0
- data/lib/live_ast/replace_raise.rb +21 -0
- data/lib/live_ast/to_ast.rb +17 -0
- data/lib/live_ast/to_ruby.rb +12 -0
- data/lib/live_ast/version.rb +3 -0
- data/lib/live_ast.rb +4 -0
- data/test/ast_eval_feature_test.rb +11 -0
- data/test/ast_load_feature_test.rb +11 -0
- data/test/backtrace_test.rb +159 -0
- data/test/covert_define_method_test.rb +23 -0
- data/test/def_test.rb +35 -0
- data/test/define_method_test.rb +41 -0
- data/test/define_singleton_method_test.rb +15 -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/usascii.rb +6 -0
- data/test/encoding_test/utf8.rb +6 -0
- data/test/encoding_test.rb +51 -0
- data/test/error_test.rb +115 -0
- data/test/eval_test.rb +269 -0
- data/test/flush_cache_test.rb +98 -0
- data/test/lambda_test.rb +56 -0
- data/test/load_path_test.rb +84 -0
- data/test/load_test.rb +85 -0
- data/test/noninvasive_test.rb +51 -0
- data/test/readme_test.rb +11 -0
- data/test/recursive_eval_test.rb +52 -0
- data/test/redefine_method_test.rb +83 -0
- data/test/reload_test.rb +108 -0
- data/test/shared/ast_generators.rb +124 -0
- data/test/shared/main.rb +110 -0
- data/test/stdlib_test.rb +11 -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 +86 -0
- metadata +223 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative 'shared/main'
|
2
|
+
|
3
|
+
class CovertDefineMethodTest < RegularTest
|
4
|
+
DEFINE = lambda do
|
5
|
+
class A
|
6
|
+
def A.my_def(*args, &block)
|
7
|
+
define_method(*args, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
my_def :h do |x, y|
|
11
|
+
x + y
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_covert_define_method
|
17
|
+
DEFINE.call
|
18
|
+
assert_equal 77, A.new.h(33, 44)
|
19
|
+
|
20
|
+
assert_equal binop_covert_define_method(:h, :+, :my_def),
|
21
|
+
A.instance_method(:h).to_ast
|
22
|
+
end
|
23
|
+
end
|
data/test/def_test.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'shared/main'
|
2
|
+
|
3
|
+
class DefTest < RegularTest
|
4
|
+
class A
|
5
|
+
def f
|
6
|
+
"A#f"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_def_unbound_method_a
|
11
|
+
expected = no_arg_def(:f, "A#f")
|
12
|
+
assert_equal expected, A.instance_method(:f).to_ast
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_def_method_a
|
16
|
+
expected = no_arg_def(:f, "A#f")
|
17
|
+
assert_equal expected, A.new.method(:f).to_ast
|
18
|
+
end
|
19
|
+
|
20
|
+
class B
|
21
|
+
def f(x, y)
|
22
|
+
x + y
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_def_unbound_method_b
|
27
|
+
expected = binop_def(:f, :+)
|
28
|
+
assert_equal expected, B.instance_method(:f).to_ast
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_def_instance_method_b
|
32
|
+
expected = binop_def(:f, :+)
|
33
|
+
assert_equal expected, B.new.method(:f).to_ast
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative 'shared/main'
|
2
|
+
|
3
|
+
class DefineMethodTest < RegularTest
|
4
|
+
DEFINE = lambda do
|
5
|
+
class A
|
6
|
+
{
|
7
|
+
:f => :+,
|
8
|
+
:g => :*,
|
9
|
+
:h => :-,
|
10
|
+
}.each_pair do |name, op|
|
11
|
+
case op
|
12
|
+
when :+
|
13
|
+
define_method name do |x, y|
|
14
|
+
x + y
|
15
|
+
end
|
16
|
+
when :*
|
17
|
+
define_method name do |x, y|
|
18
|
+
x * y
|
19
|
+
end
|
20
|
+
when :-
|
21
|
+
define_method name do |x, y|
|
22
|
+
x - y
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_define_method
|
30
|
+
DEFINE.call
|
31
|
+
|
32
|
+
assert_equal binop_define_method_with_var(:name, :+),
|
33
|
+
A.instance_method(:f).to_ast
|
34
|
+
|
35
|
+
assert_equal binop_define_method_with_var(:name, :*),
|
36
|
+
A.instance_method(:g).to_ast
|
37
|
+
|
38
|
+
assert_equal binop_define_method_with_var(:name, :-),
|
39
|
+
A.instance_method(:h).to_ast
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative 'shared/main'
|
2
|
+
|
3
|
+
class DefineSingletonMethodTest < RegularTest
|
4
|
+
def test_define_singleton_method
|
5
|
+
a = Object.new
|
6
|
+
a.define_singleton_method :f do |x, y|
|
7
|
+
x + y
|
8
|
+
end
|
9
|
+
|
10
|
+
assert_equal 77, a.f(33, 44)
|
11
|
+
|
12
|
+
assert_equal binop_define_singleton_method(:f, :+, :a),
|
13
|
+
a.singleton_class.instance_method(:f).to_ast
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# encoding: feynman-diagram
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require_relative 'shared/main'
|
2
|
+
|
3
|
+
require_relative 'encoding_test/default.rb'
|
4
|
+
require_relative 'encoding_test/usascii.rb'
|
5
|
+
require_relative 'encoding_test/utf8.rb'
|
6
|
+
require_relative 'encoding_test/cp932.rb'
|
7
|
+
require_relative 'encoding_test/eucjp.rb'
|
8
|
+
require_relative 'encoding_test/koi8.rb'
|
9
|
+
require_relative 'encoding_test/koi8_shebang.rb'
|
10
|
+
|
11
|
+
class AllEncodingTest < RegularTest
|
12
|
+
include EncodingTest
|
13
|
+
|
14
|
+
%w[
|
15
|
+
|
16
|
+
default US-ASCII
|
17
|
+
usascii US-ASCII
|
18
|
+
utf8 UTF-8
|
19
|
+
cp932 Windows-31J
|
20
|
+
eucjp EUC-JP
|
21
|
+
koi8 KOI8-R
|
22
|
+
koi8_shebang KOI8-R
|
23
|
+
|
24
|
+
].each_slice(2) do |abbr, name|
|
25
|
+
define_method "test_#{abbr}" do
|
26
|
+
str = send("#{abbr}_string")
|
27
|
+
assert_equal name, str.encoding.to_s
|
28
|
+
|
29
|
+
ast = EncodingTest.instance_method("#{abbr}_string").to_ast
|
30
|
+
assert_equal name, no_arg_def_return(ast).encoding.to_s
|
31
|
+
|
32
|
+
LiveAST.load "./test/encoding_test/#{abbr}.rb"
|
33
|
+
|
34
|
+
ast = EncodingTest.instance_method("#{abbr}_string").to_ast
|
35
|
+
assert_equal name, no_arg_def_return(ast).encoding.to_s
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_bad
|
40
|
+
orig = assert_raise ArgumentError do
|
41
|
+
require "./test/encoding_test/bad.rb"
|
42
|
+
end
|
43
|
+
live = assert_raise ArgumentError do
|
44
|
+
LiveAST.load "./test/encoding_test/bad.rb"
|
45
|
+
end
|
46
|
+
# inconsistent punctuation from Ruby
|
47
|
+
re = %r!\Aunknown encoding name\s*[-:]\s*feynman-diagram\Z!
|
48
|
+
assert_match re, orig.message
|
49
|
+
assert_match re, live.message
|
50
|
+
end
|
51
|
+
end
|
data/test/error_test.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
require_relative 'shared/main'
|
2
|
+
|
3
|
+
class ErrorTest < RegularTest
|
4
|
+
def test_multiple_lambda_same_line
|
5
|
+
a = lambda { } ; b = lambda { }
|
6
|
+
|
7
|
+
assert_raise LiveAST::MultipleDefinitionsOnSameLineError do
|
8
|
+
a.to_ast
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
DEFINE_A = lambda do
|
13
|
+
class A
|
14
|
+
def f ; end ; def g ; end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_multi_defs
|
19
|
+
DEFINE_A.call
|
20
|
+
assert_raise LiveAST::MultipleDefinitionsOnSameLineError do
|
21
|
+
A.instance_method(:f).to_ast
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_ast_not_found
|
26
|
+
assert_raise LiveAST::NoSourceError do
|
27
|
+
File.method(:open).to_ast
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_arg_error_too_many
|
32
|
+
orig = assert_raises ArgumentError do
|
33
|
+
eval("s", binding, "f", 99, nil)
|
34
|
+
end
|
35
|
+
|
36
|
+
live = assert_raises ArgumentError do
|
37
|
+
ast_eval("s", binding, "f", 99, nil)
|
38
|
+
end
|
39
|
+
|
40
|
+
assert_equal orig.message.sub("1..4", "2..4"), live.message
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_bad_args
|
44
|
+
[99, Object.new, File].each do |bad|
|
45
|
+
orig = assert_raises TypeError do
|
46
|
+
eval(bad, binding)
|
47
|
+
end
|
48
|
+
live = assert_raises TypeError do
|
49
|
+
ast_eval(bad, binding)
|
50
|
+
end
|
51
|
+
assert_equal orig.message, live.message
|
52
|
+
|
53
|
+
orig = assert_raises TypeError do
|
54
|
+
eval("3 + 4", binding, bad)
|
55
|
+
end
|
56
|
+
live = assert_raises TypeError do
|
57
|
+
ast_eval("3 + 4", binding, bad)
|
58
|
+
end
|
59
|
+
assert_equal orig.message, live.message
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_raw_eval
|
64
|
+
f = eval("lambda { }")
|
65
|
+
assert_raises LiveAST::RawEvalError do
|
66
|
+
f.to_ast
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_reload_with_raw_eval_1
|
71
|
+
ast_eval("lambda { }", binding)
|
72
|
+
eval("lambda { }")
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_reload_with_raw_eval_2
|
76
|
+
c = ast_eval %{
|
77
|
+
Class.new do
|
78
|
+
def f
|
79
|
+
end
|
80
|
+
end
|
81
|
+
}, binding
|
82
|
+
c.module_eval do
|
83
|
+
eval %{
|
84
|
+
remove_method :f
|
85
|
+
def f(x, y)
|
86
|
+
x + y
|
87
|
+
end
|
88
|
+
}
|
89
|
+
nil
|
90
|
+
end
|
91
|
+
|
92
|
+
assert_raises LiveAST::RawEvalError do
|
93
|
+
c.instance_method(:f).to_ast
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_bad_binding
|
98
|
+
orig = assert_raises TypeError do
|
99
|
+
eval("", "bogus")
|
100
|
+
end
|
101
|
+
|
102
|
+
live = assert_raises TypeError do
|
103
|
+
ast_eval("", "bogus")
|
104
|
+
end
|
105
|
+
|
106
|
+
assert_equal orig.message, live.message
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_shenanigans
|
110
|
+
error = assert_raises RuntimeError do
|
111
|
+
LiveAST.load "foo.rb|ast@4"
|
112
|
+
end
|
113
|
+
assert_match(/revision token/, error.message)
|
114
|
+
end
|
115
|
+
end
|
data/test/eval_test.rb
ADDED
@@ -0,0 +1,269 @@
|
|
1
|
+
require_relative 'shared/main'
|
2
|
+
|
3
|
+
class EvalTest < RegularTest
|
4
|
+
DEFINE_A = lambda do
|
5
|
+
class A
|
6
|
+
ast_eval %{
|
7
|
+
def f(x, y)
|
8
|
+
x + y
|
9
|
+
end
|
10
|
+
}, binding
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_eval_method
|
15
|
+
DEFINE_A.call
|
16
|
+
assert_equal "#{self.class}::A", A.name
|
17
|
+
assert_equal A, A.instance_method(:f).owner
|
18
|
+
|
19
|
+
assert_equal binop_def(:f, :+),
|
20
|
+
A.instance_method(:f).to_ast
|
21
|
+
|
22
|
+
assert_equal binop_def(:f, :+),
|
23
|
+
A.new.method(:f).to_ast
|
24
|
+
end
|
25
|
+
|
26
|
+
DEFINE_B = lambda do
|
27
|
+
ast_eval %{
|
28
|
+
class B
|
29
|
+
def f(x, y)
|
30
|
+
x * y
|
31
|
+
end
|
32
|
+
end
|
33
|
+
}, binding
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_eval_class
|
37
|
+
DEFINE_B.call
|
38
|
+
assert_equal "#{self.class}::B", B.name
|
39
|
+
assert_equal B, B.instance_method(:f).owner
|
40
|
+
|
41
|
+
assert_equal binop_def(:f, :*),
|
42
|
+
B.instance_method(:f).to_ast
|
43
|
+
|
44
|
+
assert_equal binop_def(:f, :*),
|
45
|
+
B.new.method(:f).to_ast
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_eval_method_anon
|
49
|
+
klass = Class.new do
|
50
|
+
ast_eval %{
|
51
|
+
def f(x, y)
|
52
|
+
x - y
|
53
|
+
end
|
54
|
+
}, binding
|
55
|
+
end
|
56
|
+
|
57
|
+
assert_nil klass.name
|
58
|
+
assert_equal klass, klass.instance_method(:f).owner
|
59
|
+
|
60
|
+
assert_equal binop_def(:f, :-),
|
61
|
+
klass.instance_method(:f).to_ast
|
62
|
+
|
63
|
+
assert_equal binop_def(:f, :-),
|
64
|
+
klass.new.method(:f).to_ast
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_eval_class_anon
|
68
|
+
klass = ast_eval %{
|
69
|
+
Class.new do
|
70
|
+
def f(x, y)
|
71
|
+
x / y
|
72
|
+
end
|
73
|
+
end
|
74
|
+
}, binding
|
75
|
+
|
76
|
+
assert_nil klass.name
|
77
|
+
assert_equal klass, klass.instance_method(:f).owner
|
78
|
+
|
79
|
+
assert_equal binop_def(:f, :/),
|
80
|
+
klass.instance_method(:f).to_ast
|
81
|
+
|
82
|
+
assert_equal binop_def(:f, :/),
|
83
|
+
klass.new.method(:f).to_ast
|
84
|
+
end
|
85
|
+
|
86
|
+
DEFINE_C = lambda do
|
87
|
+
class C
|
88
|
+
ast_eval %{
|
89
|
+
define_method :g do |x, y|
|
90
|
+
x + y
|
91
|
+
end
|
92
|
+
}, binding
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_eval_method_dynamic
|
97
|
+
DEFINE_C.call
|
98
|
+
assert_equal "#{self.class}::C", C.name
|
99
|
+
assert_equal C, C.instance_method(:g).owner
|
100
|
+
|
101
|
+
assert_equal binop_define_method(:g, :+),
|
102
|
+
C.instance_method(:g).to_ast
|
103
|
+
|
104
|
+
assert_equal binop_define_method(:g, :+),
|
105
|
+
C.new.method(:g).to_ast
|
106
|
+
end
|
107
|
+
|
108
|
+
DEFINE_D = lambda do
|
109
|
+
ast_eval %{
|
110
|
+
class D
|
111
|
+
define_method :g do |x, y|
|
112
|
+
x * y
|
113
|
+
end
|
114
|
+
end
|
115
|
+
}, binding
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_eval_class_dynamic
|
119
|
+
DEFINE_D.call
|
120
|
+
assert_equal "#{self.class}::D", D.name
|
121
|
+
assert_equal D, D.instance_method(:g).owner
|
122
|
+
|
123
|
+
assert_equal binop_define_method(:g, :*),
|
124
|
+
D.instance_method(:g).to_ast
|
125
|
+
|
126
|
+
assert_equal binop_define_method(:g, :*),
|
127
|
+
D.new.method(:g).to_ast
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_eval_method_anon_dynamic
|
131
|
+
klass = Class.new do
|
132
|
+
ast_eval %{
|
133
|
+
define_method :g do |x, y|
|
134
|
+
x - y
|
135
|
+
end
|
136
|
+
}, binding
|
137
|
+
end
|
138
|
+
|
139
|
+
assert_nil klass.name
|
140
|
+
assert_equal klass, klass.instance_method(:g).owner
|
141
|
+
|
142
|
+
assert_equal binop_define_method(:g, :-),
|
143
|
+
klass.instance_method(:g).to_ast
|
144
|
+
|
145
|
+
assert_equal binop_define_method(:g, :-),
|
146
|
+
klass.new.method(:g).to_ast
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_eval_class_anon_dynamic
|
150
|
+
klass = ast_eval %{
|
151
|
+
Class.new do
|
152
|
+
define_method :g do |x, y|
|
153
|
+
x / y
|
154
|
+
end
|
155
|
+
end
|
156
|
+
}, binding
|
157
|
+
|
158
|
+
assert_nil klass.name
|
159
|
+
assert_equal klass, klass.instance_method(:g).owner
|
160
|
+
|
161
|
+
assert_equal binop_define_method(:g, :/),
|
162
|
+
klass.instance_method(:g).to_ast
|
163
|
+
|
164
|
+
assert_equal binop_define_method(:g, :/),
|
165
|
+
klass.new.method(:g).to_ast
|
166
|
+
end
|
167
|
+
|
168
|
+
DEFINE_GH = lambda do
|
169
|
+
ast_eval %{
|
170
|
+
class G
|
171
|
+
def f
|
172
|
+
"G#f"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
class H
|
177
|
+
def g
|
178
|
+
"H#g"
|
179
|
+
end
|
180
|
+
end
|
181
|
+
}, binding
|
182
|
+
end
|
183
|
+
|
184
|
+
def test_reuse_string
|
185
|
+
DEFINE_GH.call
|
186
|
+
assert_equal "#{self.class}::G", G.name
|
187
|
+
assert_equal "#{self.class}::H", H.name
|
188
|
+
|
189
|
+
assert_equal no_arg_def(:f, "G#f"),
|
190
|
+
G.instance_method(:f).to_ast
|
191
|
+
|
192
|
+
assert_equal no_arg_def(:f, "G#f"),
|
193
|
+
G.new.method(:f).to_ast
|
194
|
+
|
195
|
+
assert_equal no_arg_def(:g, "H#g"),
|
196
|
+
H.instance_method(:g).to_ast
|
197
|
+
|
198
|
+
assert_equal no_arg_def(:g, "H#g"),
|
199
|
+
H.new.method(:g).to_ast
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_module_eval
|
203
|
+
klass = Class.new
|
204
|
+
klass.module_eval do
|
205
|
+
ast_eval %{
|
206
|
+
def f
|
207
|
+
"z"
|
208
|
+
end
|
209
|
+
}, binding
|
210
|
+
end
|
211
|
+
|
212
|
+
assert_equal klass, klass.instance_method(:f).owner
|
213
|
+
|
214
|
+
assert_equal no_arg_def(:f, "z"),
|
215
|
+
klass.instance_method(:f).to_ast
|
216
|
+
|
217
|
+
assert_equal no_arg_def(:f, "z"),
|
218
|
+
klass.new.method(:f).to_ast
|
219
|
+
end
|
220
|
+
|
221
|
+
def test_singleton_class
|
222
|
+
obj = Object.new
|
223
|
+
obj.singleton_class.module_eval do
|
224
|
+
ast_eval %{
|
225
|
+
def f
|
226
|
+
"singleton"
|
227
|
+
end
|
228
|
+
}, binding
|
229
|
+
end
|
230
|
+
|
231
|
+
assert_equal no_arg_def(:f, "singleton"),
|
232
|
+
obj.method(:f).to_ast
|
233
|
+
end
|
234
|
+
|
235
|
+
def test_proc_in_eval
|
236
|
+
a = ast_eval %{ proc { |x, y| x + y } }, binding
|
237
|
+
|
238
|
+
assert_equal binop_block(:proc, :+), a.to_ast
|
239
|
+
end
|
240
|
+
|
241
|
+
def test_proc_new_in_eval
|
242
|
+
a = ast_eval %{ Proc.new { |x, y| x * y } }, binding
|
243
|
+
|
244
|
+
assert_equal binop_proc_new(:*), a.to_ast
|
245
|
+
end
|
246
|
+
|
247
|
+
def test_method_block_in_eval
|
248
|
+
a = ast_eval %{ return_block { |x, y| x - y } }, binding
|
249
|
+
|
250
|
+
assert_equal binop_block(:return_block, :-), a.to_ast
|
251
|
+
end
|
252
|
+
|
253
|
+
def test_lambda_in_eval
|
254
|
+
a = ast_eval %{ lambda { |x, y| x / y } }, binding
|
255
|
+
|
256
|
+
assert_equal binop_block(:lambda, :/), a.to_ast
|
257
|
+
|
258
|
+
# sanity check
|
259
|
+
assert_not_equal binop_block(:lambda, :+), a.to_ast
|
260
|
+
end
|
261
|
+
|
262
|
+
# from rubyspec
|
263
|
+
def test_to_str_on_file
|
264
|
+
file = MiniTest::Mock.new
|
265
|
+
file.expect(:to_str, "zebra.rb")
|
266
|
+
ast_eval "33 + 44", binding, file
|
267
|
+
file.verify
|
268
|
+
end
|
269
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require_relative 'shared/main'
|
2
|
+
|
3
|
+
# test for flushing side-effects: unsort this TestCase from other
|
4
|
+
# TestCases.
|
5
|
+
|
6
|
+
define_unsorted_test_case "FlushCacheTest", RegularTest do
|
7
|
+
def test_cache
|
8
|
+
# testing global state of cache -- must be sequential
|
9
|
+
uncached_method_from_require
|
10
|
+
uncached_method_from_eval
|
11
|
+
cached_method_from_eval
|
12
|
+
lost_method_from_require
|
13
|
+
flush_lambda
|
14
|
+
end
|
15
|
+
|
16
|
+
def uncached_method_from_require
|
17
|
+
klass = Class.new do
|
18
|
+
def f ; end
|
19
|
+
def g ; end
|
20
|
+
end
|
21
|
+
|
22
|
+
LiveAST.flush_cache
|
23
|
+
|
24
|
+
#
|
25
|
+
# file never made it into the cache; unaffected by flush
|
26
|
+
#
|
27
|
+
assert_nothing_raised do
|
28
|
+
klass.instance_method(:g).to_ast
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def uncached_method_from_eval
|
33
|
+
klass = Class.new do
|
34
|
+
ast_eval %{
|
35
|
+
def f ; end
|
36
|
+
def g ; end
|
37
|
+
}, binding
|
38
|
+
end
|
39
|
+
|
40
|
+
LiveAST.flush_cache
|
41
|
+
|
42
|
+
assert_raise LiveAST::FlushedError do
|
43
|
+
klass.instance_method(:g).to_ast
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def cached_method_from_eval
|
48
|
+
klass = Class.new do
|
49
|
+
ast_eval %{
|
50
|
+
def f ; end
|
51
|
+
def g ; end
|
52
|
+
}, binding
|
53
|
+
end
|
54
|
+
|
55
|
+
f_ast = klass.instance_method(:f).to_ast
|
56
|
+
|
57
|
+
LiveAST.flush_cache
|
58
|
+
|
59
|
+
assert_equal f_ast.object_id,
|
60
|
+
klass.instance_method(:f).to_ast.object_id
|
61
|
+
|
62
|
+
assert_raise LiveAST::FlushedError do
|
63
|
+
klass.instance_method(:g).to_ast
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def lost_method_from_require
|
68
|
+
klass = Class.new do
|
69
|
+
def f ; end
|
70
|
+
def g ; end
|
71
|
+
end
|
72
|
+
|
73
|
+
# check that previous flushing did not cause side effect
|
74
|
+
assert_nothing_raised do
|
75
|
+
klass.instance_method(:f).to_ast
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def flush_lambda
|
80
|
+
a, b = ast_eval %{
|
81
|
+
[
|
82
|
+
lambda { "aaa" },
|
83
|
+
lambda { "bbb" },
|
84
|
+
]
|
85
|
+
}, binding
|
86
|
+
|
87
|
+
a_ast = a.to_ast
|
88
|
+
assert_equal no_arg_block(:lambda, "aaa"), a_ast
|
89
|
+
|
90
|
+
LiveAST.flush_cache
|
91
|
+
|
92
|
+
assert_equal a_ast.object_id, a.to_ast.object_id
|
93
|
+
|
94
|
+
assert_raise LiveAST::FlushedError do
|
95
|
+
b.to_ast
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|