subaltern 1.0.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.
@@ -0,0 +1,251 @@
1
+
2
+ require 'spec_helper'
3
+
4
+
5
+ describe Subaltern do
6
+
7
+ describe 'if' do
8
+
9
+ it 'works (then)' do
10
+
11
+ Subaltern.eval(%{
12
+ if true
13
+ :ok
14
+ end
15
+ }).should == :ok
16
+ end
17
+
18
+ it 'works (complex expression)' do
19
+
20
+ Subaltern.eval(%{
21
+ if false or true
22
+ :ok
23
+ end
24
+ }).should == :ok
25
+ end
26
+
27
+ it 'works (else)' do
28
+
29
+ Subaltern.eval(%{
30
+ if false
31
+ :not_ok
32
+ else
33
+ :ok
34
+ end
35
+ }).should == :ok
36
+ end
37
+
38
+ it 'works postfix' do
39
+
40
+ Subaltern.eval(%{
41
+ 'ok' if true
42
+ }).should == 'ok'
43
+ end
44
+ end
45
+
46
+ describe 'elsif' do
47
+
48
+ it 'works' do
49
+
50
+ Subaltern.eval(%{
51
+ if false
52
+ :not_ok
53
+ elsif true
54
+ :ok
55
+ else
56
+ :really_not_ok
57
+ end
58
+ }).should == :ok
59
+ end
60
+ end
61
+
62
+ describe 'unless' do
63
+
64
+ it 'works' do
65
+
66
+ Subaltern.eval(%{
67
+ unless false
68
+ :ok
69
+ else
70
+ :not_ok
71
+ end
72
+ }).should == :ok
73
+ end
74
+ end
75
+
76
+ describe 'case' do
77
+
78
+ it 'works' do
79
+
80
+ Subaltern.eval(%{
81
+ case true
82
+ when true then :ok
83
+ when false then :not_ok
84
+ else :really_not_ok
85
+ end
86
+ }).should == :ok
87
+ end
88
+
89
+ it 'works (else)' do
90
+
91
+ Subaltern.eval(%{
92
+ case false
93
+ when true then :not_ok
94
+ else :ok
95
+ end
96
+ }).should == :ok
97
+ end
98
+
99
+ it 'works (multiline)' do
100
+
101
+ Subaltern.eval(%{
102
+ case true
103
+ when true
104
+ :not_ok
105
+ :ok
106
+ else
107
+ :really_not_ok
108
+ end
109
+ }).should == :ok
110
+ end
111
+
112
+ it 'works (classes)' do
113
+
114
+ Subaltern.eval(%{
115
+ case true
116
+ when FalseClass
117
+ :not_ok
118
+ when TrueClass
119
+ :ok
120
+ else
121
+ :really_not_ok
122
+ end
123
+ }).should == :ok
124
+ end
125
+
126
+ it 'works (regexes)' do
127
+
128
+ Subaltern.eval(%{
129
+ case 'the little bird'
130
+ when /fox/
131
+ :not_ok
132
+ when /bird/
133
+ :ok
134
+ else
135
+ :really_not_ok
136
+ end
137
+ }).should == :ok
138
+ end
139
+
140
+ it 'works (regexes 2)' do
141
+
142
+ Subaltern.eval(%{
143
+ case 'the little bird'
144
+ when /squirrel/
145
+ :not_ok
146
+ when /chipmunk/
147
+ :really_not_ok
148
+ else
149
+ :ok
150
+ end
151
+ }).should == :ok
152
+ end
153
+ end
154
+
155
+ context '#each' do
156
+
157
+ describe 'break' do
158
+
159
+ it 'works' do
160
+
161
+ Subaltern.eval(%{
162
+ [ 1, 2, 3 ].each do |i|
163
+ break
164
+ end
165
+ }).should == nil
166
+ end
167
+ end
168
+
169
+ describe 'break y' do
170
+
171
+ it 'works' do
172
+
173
+ Subaltern.eval(%{
174
+ [ 1, 2, 3 ].each do |i|
175
+ break i
176
+ end
177
+ }).should == 1
178
+ end
179
+ end
180
+
181
+ describe 'next' do
182
+
183
+ it 'works' do
184
+
185
+ Subaltern.eval(%{
186
+ a = []
187
+ [ 1, 2, 3 ].each do |i|
188
+ next
189
+ a << i
190
+ end
191
+ a
192
+ }).should == []
193
+ end
194
+ end
195
+ end
196
+
197
+ context '#collect' do
198
+
199
+ describe 'next x' do
200
+
201
+ it 'works' do
202
+
203
+ Subaltern.eval(%{
204
+ [ 1, 2, 3 ].collect do |i|
205
+ next i * 3
206
+ end
207
+ }).should == [ 3, 6, 9 ]
208
+ end
209
+
210
+ it 'works with multiple values' do
211
+
212
+ Subaltern.eval(%{
213
+ [ 1, 2, 3 ].collect do |i|
214
+ next i, i * 3
215
+ end
216
+ }).should == [ [ 1, 3 ], [ 2, 6 ], [ 3, 9 ] ]
217
+ end
218
+ end
219
+ end
220
+
221
+ describe '#?' do
222
+
223
+ it 'works' do
224
+
225
+ Subaltern.eval(%{
226
+ true ? 1 : 0
227
+ }).should == 1
228
+ end
229
+
230
+ it 'works (then)' do
231
+
232
+ Subaltern.eval(%{
233
+ false ? 0 : 1
234
+ }).should == 1
235
+ end
236
+ end
237
+
238
+ describe 'rescue' do
239
+
240
+ describe 'rescue :x' do
241
+
242
+ it 'works' do
243
+
244
+ Subaltern.eval(%{
245
+ 1 / 0 rescue :limit
246
+ }).should == :limit
247
+ end
248
+ end
249
+ end
250
+ end
251
+
@@ -0,0 +1,106 @@
1
+
2
+ require 'spec_helper'
3
+
4
+
5
+ class String
6
+ def constantize
7
+ eval(self)
8
+ end
9
+ end
10
+
11
+ describe Subaltern do
12
+
13
+ context 'evil' do
14
+
15
+ describe "''.eval('1 + 1')" do
16
+
17
+ it 'raises' do
18
+
19
+ lambda {
20
+ Subaltern.eval("''.eval('1 + 1')")
21
+ }.should raise_error(Subaltern::NonWhitelistedMethodError)
22
+ end
23
+ end
24
+
25
+ describe 'calls on non-whitelisted classes' do
26
+
27
+ it 'raises' do
28
+
29
+ lambda {
30
+ Subaltern.eval("'File'.constantize.read('#{__FILE__}')")
31
+ #}.should raise_error(Subaltern::NonWhitelistedClassError)
32
+ }.should raise_error(Subaltern::NonWhitelistedMethodError)
33
+ end
34
+ end
35
+
36
+ describe 'a constant lookup' do
37
+
38
+ it 'raises (ENV)' do
39
+
40
+ lambda {
41
+ Subaltern.eval('ENV')
42
+ }.should raise_error(Subaltern::AccessError)
43
+ end
44
+
45
+ it 'raises (File::Utils)' do
46
+
47
+ lambda {
48
+ Subaltern.eval('File::Utils')
49
+ }.should raise_error(Subaltern::AccessError)
50
+ end
51
+ end
52
+
53
+ describe 'a call on a constant' do
54
+
55
+ it 'raises (ENV["HOME"])' do
56
+
57
+ lambda {
58
+ Subaltern.eval('ENV["HOME"]')
59
+ }.should raise_error(Subaltern::AccessError)
60
+ end
61
+ end
62
+
63
+ describe 'a global variable lookup' do
64
+
65
+ it 'raises ($nada)' do
66
+
67
+ lambda {
68
+ Subaltern.eval('$nada')
69
+ }.should raise_error(Subaltern::AccessError)
70
+ end
71
+ end
72
+
73
+ describe 'backquoting' do
74
+
75
+ it 'raises (simple case)' do
76
+
77
+ lambda {
78
+ Subaltern.eval('`ls -al`')
79
+ }.should raise_error(Subaltern::AccessError)
80
+ end
81
+
82
+ it 'raises (string extrapolation case)' do
83
+
84
+ lambda {
85
+ Subaltern.eval('`ls -al #{nada}`')
86
+ }.should raise_error(Subaltern::AccessError)
87
+ end
88
+ end
89
+
90
+ describe 'method with a block' do
91
+
92
+ it 'is not automatically whitelisted' do
93
+
94
+ class Array
95
+ def whatever
96
+ end
97
+ end
98
+
99
+ lambda {
100
+ Subaltern.eval('[].whatever { |e| false }')
101
+ }.should raise_error(Subaltern::NonWhitelistedMethodError)
102
+ end
103
+ end
104
+ end
105
+ end
106
+
@@ -0,0 +1,20 @@
1
+
2
+ require 'spec_helper'
3
+
4
+
5
+ describe Subaltern do
6
+
7
+ describe 'Fixnum' do
8
+
9
+ it 'works' do
10
+
11
+ Subaltern.eval('1.0').should == 1.0
12
+ Subaltern.eval('1 + 1').should == 2
13
+ Subaltern.eval('1 * 2').should == 2
14
+ Subaltern.eval('3 - 1').should == 2
15
+ Subaltern.eval('1.even?').should == false
16
+ Subaltern.eval('1.odd?').should == true
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,123 @@
1
+
2
+ require 'spec_helper'
3
+
4
+
5
+ describe Subaltern do
6
+
7
+ context 'functions' do
8
+
9
+ it 'accepts function definitions' do
10
+
11
+ Subaltern.eval(%{
12
+ def addition(a, b)
13
+ a + b
14
+ end
15
+ }).should == nil
16
+ end
17
+
18
+ it 'accepts calls to defined functions' do
19
+
20
+ Subaltern.eval(%{
21
+ def addition(a, b)
22
+ a + b
23
+ end
24
+ addition(1, 2)
25
+ }).should == 3
26
+ end
27
+
28
+ it 'accepts functions with optional parameters' do
29
+
30
+ Subaltern.eval(%{
31
+ def add(a, b=1, c=2)
32
+ a + b + c
33
+ end
34
+ [ add(1, 2), add(4) ]
35
+ }).should == [ 5, 7 ]
36
+ end
37
+
38
+ it 'accepts functions with starred parameters' do
39
+
40
+ Subaltern.eval(%{
41
+ def concat(a, *args)
42
+ [ a ] + args
43
+ end
44
+ concat(1, 2, 3, 4)
45
+ }).should == [ 1, 2, 3, 4 ]
46
+ end
47
+
48
+ it 'accepts a final hash argument' do
49
+
50
+ Subaltern.eval(%{
51
+ def pretty(a, b)
52
+ [ a, b ]
53
+ end
54
+ pretty('a', 'b' => 'c')
55
+ }).should == [ 'a', { 'b' => 'c' } ]
56
+ end
57
+
58
+ it 'accepts "return" in the middle of functions' do
59
+
60
+ Subaltern.eval(%{
61
+ def hello
62
+ 1
63
+ return 'nada'
64
+ 2
65
+ end
66
+ hello
67
+ }).should == 'nada'
68
+ end
69
+
70
+ it 'accepts functions with blocks' do
71
+
72
+ Subaltern.eval(%{
73
+ def hello
74
+ 1 + yield
75
+ end
76
+ hello { 3 }
77
+ }).should == 4
78
+ end
79
+
80
+ it 'accepts functions with explicit blocks' do
81
+
82
+ Subaltern.eval(%{
83
+ def hello(start, &block)
84
+ start + block.call
85
+ end
86
+ hello(1) { 3 }
87
+ }).should == 4
88
+ end
89
+
90
+ it 'accepts functions that call blocks with arguments' do
91
+
92
+ Subaltern.eval(%{
93
+ def hello(start, &block)
94
+ start + block.call(start)
95
+ end
96
+ hello(3) { |s| s * 3 }
97
+ }).should == 12
98
+ end
99
+
100
+ it 'accepts functions that yield arguments to blocks' do
101
+
102
+ Subaltern.eval(%{
103
+ def hello(start)
104
+ start + yield(start)
105
+ end
106
+ hello(3) { |s| s * 3 }
107
+ }).should == 12
108
+ end
109
+
110
+ it 'raises when a block is called without its arg' do
111
+
112
+ lambda {
113
+ Subaltern.eval(%{
114
+ def hello(start, &block)
115
+ start + block.call
116
+ end
117
+ hello(3) { |start| start * 3 }
118
+ })
119
+ }.should raise_error(Subaltern::NonWhitelistedMethodError)
120
+ end
121
+ end
122
+ end
123
+