ruby_ex 0.1.1
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/AUTHORS +51 -0
- data/ChangeLog +1763 -0
- data/NEWS +3 -0
- data/README +1 -0
- data/Rakefile +8 -0
- data/SPEC.dyn.yml +10 -0
- data/SPEC.gem.yml +269 -0
- data/SPEC.yml +36 -0
- data/src/abstract.rb +253 -0
- data/src/abstract_node.rb +85 -0
- data/src/algorithms.rb +12 -0
- data/src/algorithms/simulated_annealing.rb +142 -0
- data/src/ask.rb +100 -0
- data/src/attributed_class.rb +303 -0
- data/src/cache.rb +350 -0
- data/src/checkout.rb +12 -0
- data/src/choose.rb +271 -0
- data/src/commands.rb +20 -0
- data/src/commands/command.rb +492 -0
- data/src/commands/datas.rb +16 -0
- data/src/commands/datas/composite.rb +31 -0
- data/src/commands/datas/data.rb +65 -0
- data/src/commands/datas/factory.rb +69 -0
- data/src/commands/datas/temp.rb +26 -0
- data/src/commands/factory.rb +67 -0
- data/src/commands/helpers.rb +81 -0
- data/src/commands/pipe.rb +66 -0
- data/src/commands/runners.rb +16 -0
- data/src/commands/runners/exec.rb +50 -0
- data/src/commands/runners/fork.rb +130 -0
- data/src/commands/runners/runner.rb +140 -0
- data/src/commands/runners/system.rb +57 -0
- data/src/commands/seq.rb +32 -0
- data/src/config_file.rb +95 -0
- data/src/const_regexp.rb +57 -0
- data/src/daemon.rb +135 -0
- data/src/diff.rb +665 -0
- data/src/dlogger.rb +62 -0
- data/src/drb/drb_observable.rb +95 -0
- data/src/drb/drb_observable_pool.rb +27 -0
- data/src/drb/drb_service.rb +44 -0
- data/src/drb/drb_undumped_attributes.rb +56 -0
- data/src/drb/drb_undumped_indexed_object.rb +55 -0
- data/src/drb/insecure_protected_methods.rb +101 -0
- data/src/drb_ex.rb +12 -0
- data/src/dumpable_proc.rb +57 -0
- data/src/filetype.rb +229 -0
- data/src/generate_id.rb +44 -0
- data/src/histogram.rb +222 -0
- data/src/hookable.rb +283 -0
- data/src/hooker.rb +54 -0
- data/src/indexed_node.rb +65 -0
- data/src/io_marshal.rb +99 -0
- data/src/ioo.rb +193 -0
- data/src/labeled_node.rb +62 -0
- data/src/logger_observer.rb +24 -0
- data/src/md5sum.rb +70 -0
- data/src/module/autoload_tree.rb +65 -0
- data/src/module/hierarchy.rb +334 -0
- data/src/module/instance_method_visibility.rb +71 -0
- data/src/node.rb +81 -0
- data/src/object_monitor.rb +143 -0
- data/src/object_monitor_activity.rb +34 -0
- data/src/observable.rb +138 -0
- data/src/observable_pool.rb +291 -0
- data/src/orderedhash.rb +252 -0
- data/src/pp_hierarchy.rb +30 -0
- data/src/random_generators.rb +29 -0
- data/src/random_generators/random_generator.rb +33 -0
- data/src/random_generators/ruby.rb +25 -0
- data/src/ruby_ex.rb +124 -0
- data/src/safe_eval.rb +346 -0
- data/src/sendmail.rb +214 -0
- data/src/service_manager.rb +122 -0
- data/src/shuffle.rb +30 -0
- data/src/spring.rb +134 -0
- data/src/spring_set.rb +134 -0
- data/src/symtbl.rb +108 -0
- data/src/synflow.rb +474 -0
- data/src/thread_mutex.rb +11 -0
- data/src/timeout_ex.rb +79 -0
- data/src/trace.rb +26 -0
- data/src/uri/druby.rb +78 -0
- data/src/uri/file.rb +63 -0
- data/src/uri/ftp_ex.rb +36 -0
- data/src/uri/http_ex.rb +41 -0
- data/src/uri/pgsql.rb +136 -0
- data/src/uri/ssh.rb +87 -0
- data/src/uri/svn.rb +113 -0
- data/src/uri_ex.rb +71 -0
- data/src/verbose_object.rb +70 -0
- data/src/yaml/basenode_ext.rb +63 -0
- data/src/yaml/chop_header.rb +24 -0
- data/src/yaml/transform.rb +450 -0
- data/src/yaml/yregexpath.rb +76 -0
- data/test/algorithms/simulated_annealing_test.rb +102 -0
- data/test/check-pkg-ruby_ex.yml +15 -0
- data/test/check-ruby_ex.yml +12 -0
- data/test/resources/autoload_tree/A.rb +11 -0
- data/test/resources/autoload_tree/B.rb +10 -0
- data/test/resources/autoload_tree/foo/C.rb +18 -0
- data/test/resources/foo.txt +6 -0
- data/test/sanity-suite.yml +12 -0
- data/test/sanity/multiple-requires.yml +20 -0
- data/test/sanity/single-requires.yml +24 -0
- data/test/test-unit-setup.rb +6 -0
- data/test/unit-suite.yml +14 -0
- metadata +269 -0
data/src/pp_hierarchy.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Copyright: Copyright (c) 2004 Nicolas Despres. All rights reserved.
|
2
|
+
# Author: Nicolas Despres <polrop@lrde.epita.fr>.
|
3
|
+
# License: Gnu General Public License.
|
4
|
+
|
5
|
+
# $LastChangedBy: polrop $
|
6
|
+
# $Id: hierarchy.rb 145 2005-01-30 14:16:14Z polrop $
|
7
|
+
|
8
|
+
require 'ruby_ex'
|
9
|
+
|
10
|
+
class Hash
|
11
|
+
|
12
|
+
# Pretty print a hash symbolizing a class hierarchy.
|
13
|
+
def pp_hierarchy(prefix=//, abstract=false)
|
14
|
+
pp_hierarchy_rec('', prefix, abstract)
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
def pp_hierarchy_rec(indent, prefix, abstract)
|
19
|
+
self.each do |k, v|
|
20
|
+
k_str = k.to_s.sub(prefix, '')
|
21
|
+
if abstract and k.abstract?
|
22
|
+
puts "#{indent}/#{k_str}/"
|
23
|
+
else
|
24
|
+
puts "#{indent}#{k_str}"
|
25
|
+
end
|
26
|
+
v.pp_hierarchy_rec(indent + ' ', prefix, abstract)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end # class Hash
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2005 Nicolas Pouillard. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
# Revision:: $Id: random_generators.rb 266 2005-06-01 14:27:18Z ertai $
|
5
|
+
|
6
|
+
require 'ruby_ex'
|
7
|
+
require 'module/autoload_tree'
|
8
|
+
require 'abstract'
|
9
|
+
|
10
|
+
module RandomGenerators
|
11
|
+
|
12
|
+
autoloaded_module(__FILE__)
|
13
|
+
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def default
|
17
|
+
class << self
|
18
|
+
def default
|
19
|
+
@@default
|
20
|
+
end
|
21
|
+
end
|
22
|
+
@@default = Ruby.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def default= ( aClass )
|
26
|
+
@@default = aClass
|
27
|
+
end
|
28
|
+
|
29
|
+
end # module RandomGenerators
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2005 Nicolas Pouillard. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
# Revision:: $Id: random_generator.rb 258 2005-06-01 00:22:51Z ertai $
|
5
|
+
|
6
|
+
require 'random_generators'
|
7
|
+
|
8
|
+
module RandomGenerators
|
9
|
+
|
10
|
+
class RandomGenerator
|
11
|
+
abstract
|
12
|
+
|
13
|
+
def check_choose_integer ( n )
|
14
|
+
unless n.is_a? Integer
|
15
|
+
raise ArgumentError, "Need an integer (not #{n})"
|
16
|
+
end
|
17
|
+
if n <= 0
|
18
|
+
raise ArgumentError, "Need an positive value (not #{n})"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def check_choose_float ( f )
|
23
|
+
unless f.is_a? Float
|
24
|
+
raise ArgumentError, "Need a float (not #{f})"
|
25
|
+
end
|
26
|
+
if f <= 0
|
27
|
+
raise ArgumentError, "Need an positive value (not #{f})"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end # class RandomGenerator
|
32
|
+
|
33
|
+
end # module RandomGenerators
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2005 Nicolas Pouillard. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
# Revision:: $Id: ruby.rb 258 2005-06-01 00:22:51Z ertai $
|
5
|
+
|
6
|
+
require 'random_generators'
|
7
|
+
|
8
|
+
module RandomGenerators
|
9
|
+
|
10
|
+
class Ruby < RandomGenerator
|
11
|
+
concrete
|
12
|
+
|
13
|
+
def choose_integer ( n )
|
14
|
+
check_choose_integer(n)
|
15
|
+
Kernel.rand(n)
|
16
|
+
end
|
17
|
+
|
18
|
+
def choose_float ( f=1.0 )
|
19
|
+
check_choose_float(f)
|
20
|
+
Kernel.rand() * f
|
21
|
+
end
|
22
|
+
|
23
|
+
end # class Ruby
|
24
|
+
|
25
|
+
end # module RandomGenerators
|
data/src/ruby_ex.rb
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
# Copyright:: Copyright (c) 2005 Nicolas Pouillard. All rights reserved.
|
2
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
3
|
+
# License:: Gnu General Public License.
|
4
|
+
# Revision:: $Id: ruby_ex.rb 266 2005-06-01 14:27:18Z ertai $
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'rubygems'
|
8
|
+
require_gem 'core_ex' # FIXME version
|
9
|
+
require 'core_ex'
|
10
|
+
rescue LoadError => ex
|
11
|
+
core_ex = @@dir.parent + 'core_ex/lib/core_ex'
|
12
|
+
if core_ex.exists? and not $".include? 'core_ex.rb'
|
13
|
+
require core_ex.to_s
|
14
|
+
else
|
15
|
+
raise ex
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
module DRb
|
21
|
+
end
|
22
|
+
|
23
|
+
module Algorithms
|
24
|
+
end
|
25
|
+
|
26
|
+
module RubyEx
|
27
|
+
|
28
|
+
@@dir = Pathname.new(__FILE__).dirname.expand_path
|
29
|
+
$: << @@dir.to_s
|
30
|
+
|
31
|
+
module_function
|
32
|
+
|
33
|
+
def sources
|
34
|
+
@@contents ||= Hash.new([].freeze)
|
35
|
+
%[
|
36
|
+
abstract.rb Abstract Concrete Class
|
37
|
+
abstract_node.rb AbstractNode
|
38
|
+
algorithms.rb Algorithms
|
39
|
+
attributed_class.rb AttributedClass
|
40
|
+
cache.rb Cache
|
41
|
+
config_file.rb ConfigFile
|
42
|
+
const_regexp.rb ConstRegexp
|
43
|
+
daemon.rb Daemon
|
44
|
+
diff.rb Diff
|
45
|
+
dlogger.rb DLogger
|
46
|
+
drb.rb DRb
|
47
|
+
dumpable_proc.rb DumpableProc
|
48
|
+
filetype.rb FileType
|
49
|
+
histogram.rb Histogram
|
50
|
+
hookable.rb Hookable
|
51
|
+
hooker.rb Hooker
|
52
|
+
inactive_timeout.rb InactiveTimeout
|
53
|
+
indexed_node.rb IndexedNode
|
54
|
+
ioo.rb IOO IOOTCPSocket
|
55
|
+
killall.rb KillAll
|
56
|
+
labeled_node.rb LabeledNode
|
57
|
+
node.rb Node
|
58
|
+
object_monitor.rb ObjectMonitor
|
59
|
+
object_monitor_activity.rb ObjectMonitorActivity
|
60
|
+
observable.rb Observable
|
61
|
+
observable_pool.rb ObservablePool
|
62
|
+
orderedhash.rb OrderedHash_ext OHash
|
63
|
+
pseudo_cache.rb PseudoCache
|
64
|
+
random_generators.rb RandomGenerators
|
65
|
+
timeout_ex.rb TimeoutEx
|
66
|
+
verbose_object.rb VerboseObject
|
67
|
+
spring.rb Spring
|
68
|
+
spring_set.rb SpringSet
|
69
|
+
symtbl.rb SymTbl
|
70
|
+
synflow.rb SynFlowFactory SynFlow
|
71
|
+
safe_eval.rb SafeEval
|
72
|
+
sendmail.rb Sendmail
|
73
|
+
service_manager.rb ServiceManager
|
74
|
+
test/unit/ui/yaml/testrunner.rb Test::Unit::UI::Yaml::TestRunner
|
75
|
+
# drb/session_manager.rb DRb::SessionManager
|
76
|
+
# drb/dispatcher.rb DRb::Dispatcher
|
77
|
+
].split(/\n/).each do |line|
|
78
|
+
line.sub!(/#.*$/, '')
|
79
|
+
line.strip!
|
80
|
+
next if line =~ /^\s*$/
|
81
|
+
file, *names = line.split(/\s+/)
|
82
|
+
@@contents[@@dir + file] = names
|
83
|
+
end
|
84
|
+
@@contents.freeze
|
85
|
+
|
86
|
+
@@sources = FileList[@@dir + '**/*.rb'].exclude(/\bsession\/error.rb\b/)
|
87
|
+
|
88
|
+
class << self
|
89
|
+
def sources
|
90
|
+
@@sources
|
91
|
+
end
|
92
|
+
end
|
93
|
+
@@sources
|
94
|
+
end
|
95
|
+
|
96
|
+
def dir
|
97
|
+
@@dir
|
98
|
+
end
|
99
|
+
|
100
|
+
def each ( &block )
|
101
|
+
sources.each do |file|
|
102
|
+
block[file, @@contents[file]]
|
103
|
+
end
|
104
|
+
self
|
105
|
+
end
|
106
|
+
|
107
|
+
def autoload
|
108
|
+
each do |file, names|
|
109
|
+
names.each do |name|
|
110
|
+
name = name.split(/::/).first
|
111
|
+
Kernel.autoload(name, file.to_s)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def require
|
117
|
+
each { |file, names| file.require }
|
118
|
+
end
|
119
|
+
|
120
|
+
end # module RubyEx
|
121
|
+
|
122
|
+
# RubyEx.each { |*a| p a }
|
123
|
+
# RubyEx.require
|
124
|
+
# RubyEx.autoload
|
data/src/safe_eval.rb
ADDED
@@ -0,0 +1,346 @@
|
|
1
|
+
# Copyright: Copyright (c) 2004 Nicolas Despres. All rights reserved.
|
2
|
+
# Author: Nicolas Despres <polrop@lrde.epita.fr>.
|
3
|
+
# License: Gnu General Public License.
|
4
|
+
|
5
|
+
# $LastChangedBy: ertai $
|
6
|
+
# $Id: safe_eval.rb 266 2005-06-01 14:27:18Z ertai $
|
7
|
+
|
8
|
+
require 'ruby_ex'
|
9
|
+
|
10
|
+
class SafeEval
|
11
|
+
|
12
|
+
attr_accessor :collect, :safe
|
13
|
+
attr_reader :output
|
14
|
+
|
15
|
+
def initialize(safe=3, collect=true)
|
16
|
+
@safe = safe
|
17
|
+
@collect = collect
|
18
|
+
end
|
19
|
+
|
20
|
+
def run(code_str='', binding=nil, filename='(SafeEval)', lineno=1)
|
21
|
+
binding = yield if block_given?
|
22
|
+
lineno -= 1
|
23
|
+
@output = nil
|
24
|
+
@output = [] if @collect
|
25
|
+
result = nil
|
26
|
+
code_str.strip!
|
27
|
+
return result if code_str.empty?
|
28
|
+
rd_result, wr_result = IO.pipe
|
29
|
+
open('|-') do |io|
|
30
|
+
if io.nil? then # son
|
31
|
+
status = 0
|
32
|
+
rd_result.close
|
33
|
+
set_environment
|
34
|
+
begin
|
35
|
+
code = "$SAFE = #@safe\n#{code_str}"
|
36
|
+
result = eval(code, binding, filename, lineno)
|
37
|
+
status = 0 # needed if the user change the status
|
38
|
+
rescue Exception => exception
|
39
|
+
status = 1
|
40
|
+
result = exception
|
41
|
+
ensure
|
42
|
+
Marshal.dump(result, wr_result)
|
43
|
+
wr_result.close
|
44
|
+
exit!(status)
|
45
|
+
end
|
46
|
+
else # father
|
47
|
+
wr_result.close
|
48
|
+
io.each_line { |l| @output << l.chomp } if @collect
|
49
|
+
result = Marshal.load(rd_result)
|
50
|
+
rd_result.close
|
51
|
+
Process.waitpid(io.pid)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
raise result if $?.exitstatus == 1
|
55
|
+
@output = nil unless @collect
|
56
|
+
return result
|
57
|
+
end
|
58
|
+
public :run
|
59
|
+
|
60
|
+
# Can be overloaded to specify environment restriction.
|
61
|
+
def set_environment
|
62
|
+
end
|
63
|
+
protected :set_environment
|
64
|
+
|
65
|
+
end # class SafeEval
|
66
|
+
|
67
|
+
|
68
|
+
#
|
69
|
+
# Unit test suite
|
70
|
+
#
|
71
|
+
test_section __FILE__ do
|
72
|
+
|
73
|
+
|
74
|
+
class SafeEvalTest < Test::Unit::TestCase
|
75
|
+
|
76
|
+
#
|
77
|
+
# Tests
|
78
|
+
#
|
79
|
+
def test_interface
|
80
|
+
se = SafeEval.new
|
81
|
+
assert_respond_to(se, :run)
|
82
|
+
assert_respond_to(se, :output)
|
83
|
+
assert_respond_to(se, :safe)
|
84
|
+
assert_respond_to(se, :collect)
|
85
|
+
assert(se.protected_methods.include?('set_environment'),
|
86
|
+
"no protected method 'set_environment'")
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_nil
|
90
|
+
se = SafeEval.new
|
91
|
+
assert_equal(nil, se.run)
|
92
|
+
assert_equal([], se.output)
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_true
|
96
|
+
se = SafeEval.new
|
97
|
+
assert_equal(true, se.run('true'))
|
98
|
+
assert_equal([], se.output)
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_false
|
102
|
+
se = SafeEval.new
|
103
|
+
assert_equal(false, se.run('false'))
|
104
|
+
assert_equal([], se.output)
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_nil_no_collect
|
108
|
+
se = SafeEval.new(3, false)
|
109
|
+
assert_equal(nil, se.run)
|
110
|
+
assert_equal(nil, se.output)
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_almost_empty_code
|
114
|
+
se = SafeEval.new
|
115
|
+
assert_equal(nil, se.run(' '))
|
116
|
+
assert_equal([], se.output)
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_true_no_collect
|
120
|
+
se = SafeEval.new(3, false)
|
121
|
+
assert_equal(true, se.run('true'))
|
122
|
+
assert_equal(nil, se.output)
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_binding_argument
|
126
|
+
def getBinding; a = 42; return binding; end
|
127
|
+
se = SafeEval.new
|
128
|
+
assert_equal(nil, se.run('puts a', getBinding))
|
129
|
+
assert_equal(['42'], se.output)
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_binding_block
|
133
|
+
se = SafeEval.new
|
134
|
+
assert_equal(true, se.run('puts a; true') { a = 42; return binding })
|
135
|
+
assert_equal(['42'], se.output)
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_binding_both
|
139
|
+
def getBinding2; a = 51; return binding; end
|
140
|
+
se = SafeEval.new
|
141
|
+
ret = se.run('puts a; true', getBinding2) { a = 42; return binding }
|
142
|
+
assert_equal(true, ret)
|
143
|
+
assert_equal(['42'], se.output)
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_exception
|
147
|
+
mypid = $$
|
148
|
+
se = SafeEval.new
|
149
|
+
$tmp = 42
|
150
|
+
begin
|
151
|
+
$tmp = se.run('raise NoMethodError')
|
152
|
+
rescue NoMethodError
|
153
|
+
assert_equal(mypid, $$, "bad pid")
|
154
|
+
assert_equal(42, $tmp, "result must be nil")
|
155
|
+
assert_equal([], se.output)
|
156
|
+
ensure
|
157
|
+
assert_equal(mypid, $$, "bad pid")
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_exception_collect
|
162
|
+
se = SafeEval.new
|
163
|
+
assert_raises(Exception) do
|
164
|
+
se.run('puts "toto"; raise Exception')
|
165
|
+
end
|
166
|
+
assert_equal(['toto'], se.output)
|
167
|
+
end
|
168
|
+
|
169
|
+
# FIXME: this test block if DRb::SessionManager test suite is executed before
|
170
|
+
# this test suite in check-ruby_ex.
|
171
|
+
# def test_exception_no_collect
|
172
|
+
# se = SafeEval.new(3, false)
|
173
|
+
# assert_raises(Exception) do
|
174
|
+
# se.run('puts "toto"; raise Exception')
|
175
|
+
# end
|
176
|
+
# assert_equal(nil, se.output)
|
177
|
+
# end
|
178
|
+
|
179
|
+
def test_require_forbidden
|
180
|
+
se = SafeEval.new
|
181
|
+
assert_raises(SecurityError) do
|
182
|
+
se.run("require 'foo'")
|
183
|
+
end
|
184
|
+
assert_equal([], se.output)
|
185
|
+
end
|
186
|
+
|
187
|
+
def test_File_chmod_forbidden
|
188
|
+
se = SafeEval.new
|
189
|
+
assert_raises(SecurityError) do
|
190
|
+
se.run("File.chmod(0755, '/tmp')")
|
191
|
+
end
|
192
|
+
assert_equal([], se.output)
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_system_forbidden
|
196
|
+
se = SafeEval.new
|
197
|
+
assert_raises(SecurityError) do
|
198
|
+
se.run("system('rm /tmp/x')")
|
199
|
+
end
|
200
|
+
assert_equal([], se.output)
|
201
|
+
end
|
202
|
+
|
203
|
+
def test_system_allowed
|
204
|
+
se = SafeEval.new(2)
|
205
|
+
se.run("system(\"echo 'toto'\")")
|
206
|
+
assert_equal(['toto'], se.output)
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_print
|
210
|
+
se = SafeEval.new
|
211
|
+
assert_equal(nil, se.run('print "hello"'))
|
212
|
+
assert_equal(['hello'], se.output)
|
213
|
+
end
|
214
|
+
|
215
|
+
def test_puts
|
216
|
+
se = SafeEval.new
|
217
|
+
assert_equal(nil, se.run('puts "hello"'))
|
218
|
+
assert_equal(['hello'], se.output)
|
219
|
+
end
|
220
|
+
|
221
|
+
def test_print_no_collect
|
222
|
+
se = SafeEval.new(3, false)
|
223
|
+
assert_equal(nil, se.run('print "hello"'))
|
224
|
+
assert_equal(nil, se.output)
|
225
|
+
end
|
226
|
+
|
227
|
+
def test_puts_several_lines
|
228
|
+
se = SafeEval.new
|
229
|
+
assert_equal(nil, se.run('puts "hello\nworld"'))
|
230
|
+
assert_equal(['hello', 'world'], se.output)
|
231
|
+
end
|
232
|
+
|
233
|
+
def test_syntax_error
|
234
|
+
se = SafeEval.new
|
235
|
+
assert_raises(SyntaxError) do
|
236
|
+
se.run('4syntaxerror')
|
237
|
+
end
|
238
|
+
assert_equal([], se.output)
|
239
|
+
end
|
240
|
+
|
241
|
+
def test_bad_identifier
|
242
|
+
se = SafeEval.new
|
243
|
+
assert_raises(NameError) do
|
244
|
+
se.run('bad_identifier.directory?')
|
245
|
+
end
|
246
|
+
assert_equal([], se.output)
|
247
|
+
end
|
248
|
+
|
249
|
+
def test_syntax_error_location
|
250
|
+
se = SafeEval.new
|
251
|
+
exc = assert_raises(SyntaxError) do
|
252
|
+
se.run('4syntaxerror', nil, 'toto.yml', 1)
|
253
|
+
end
|
254
|
+
expected_message = <<EOF
|
255
|
+
compile error
|
256
|
+
toto.yml:1: syntax error
|
257
|
+
4syntaxerror
|
258
|
+
^
|
259
|
+
EOF
|
260
|
+
expected_message.chomp!
|
261
|
+
assert_equal(expected_message, exc.message)
|
262
|
+
end
|
263
|
+
|
264
|
+
def test_syntax_error_location_several_line
|
265
|
+
code = <<EOF
|
266
|
+
puts "hello"
|
267
|
+
puts "world"
|
268
|
+
4syntaxerror;
|
269
|
+
EOF
|
270
|
+
se = SafeEval.new
|
271
|
+
exc = assert_raises(SyntaxError) do
|
272
|
+
se.run(code, nil, 'toto.yml', 1)
|
273
|
+
end
|
274
|
+
expected_message = <<EOF
|
275
|
+
compile error
|
276
|
+
toto.yml:3: syntax error
|
277
|
+
4syntaxerror;
|
278
|
+
^
|
279
|
+
EOF
|
280
|
+
expected_message.chomp!
|
281
|
+
assert_equal(expected_message, exc.message)
|
282
|
+
end
|
283
|
+
|
284
|
+
def test_exit_forbidden
|
285
|
+
se = SafeEval.new(3, false)
|
286
|
+
assert_raises(SystemExit) do
|
287
|
+
se.run('exit(42)')
|
288
|
+
end
|
289
|
+
assert_equal(nil, se.output)
|
290
|
+
end
|
291
|
+
|
292
|
+
def test_exit_strong_forbidden
|
293
|
+
se = SafeEval.new
|
294
|
+
assert_raises(EOFError) do
|
295
|
+
se.run('exit!(42)')
|
296
|
+
end
|
297
|
+
assert_equal([], se.output)
|
298
|
+
end
|
299
|
+
|
300
|
+
def test_undef_me
|
301
|
+
se = SafeEval.new
|
302
|
+
assert_raises(NoMethodError) do
|
303
|
+
se.run('undef_method :run')
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
def test_read_my_var
|
308
|
+
se = SafeEval.new
|
309
|
+
str = 'puts code'
|
310
|
+
se.run(str)
|
311
|
+
assert_equal(str, se.output[-1])
|
312
|
+
end
|
313
|
+
|
314
|
+
def test_write_status
|
315
|
+
se = SafeEval.new
|
316
|
+
assert_equal(1, se.run('status = 1'))
|
317
|
+
end
|
318
|
+
|
319
|
+
def test_write_safe
|
320
|
+
se = SafeEval.new
|
321
|
+
assert_equal(1, se.run('@safe = 1'))
|
322
|
+
assert_equal(true, se.run('@safe == 3'))
|
323
|
+
end
|
324
|
+
|
325
|
+
def test_write_output
|
326
|
+
se = SafeEval.new
|
327
|
+
assert_equal(['foo'], se.run('@output << "foo"'))
|
328
|
+
assert_equal([], se.output)
|
329
|
+
end
|
330
|
+
|
331
|
+
def test_write_output_and_print
|
332
|
+
se = SafeEval.new
|
333
|
+
assert_equal(nil, se.run('@output << "foo"; p @output'))
|
334
|
+
assert_equal(["[\"foo\"]"], se.output)
|
335
|
+
end
|
336
|
+
|
337
|
+
def test_sleep
|
338
|
+
se = SafeEval.new
|
339
|
+
assert(se.run('sleep(1)') >= 1)
|
340
|
+
assert_equal([], se.output)
|
341
|
+
end
|
342
|
+
|
343
|
+
end # class SafeEvalTest
|
344
|
+
|
345
|
+
|
346
|
+
end
|