rubyless 0.3.5 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/History.txt +31 -16
- data/{README.txt → README.rdoc} +3 -3
- data/Rakefile +47 -36
- data/lib/ruby_less/basic_types.rb +15 -0
- data/lib/ruby_less/error.rb +4 -0
- data/lib/ruby_less/info.rb +3 -0
- data/lib/ruby_less/no_method_error.rb +47 -0
- data/lib/{processor.rb → ruby_less/processor.rb} +62 -23
- data/lib/{safe_class.rb → ruby_less/safe_class.rb} +87 -38
- data/lib/ruby_less/signature_hash.rb +33 -0
- data/lib/ruby_less/syntax_error.rb +4 -0
- data/lib/{typed_string.rb → ruby_less/typed_string.rb} +3 -3
- data/lib/ruby_less.rb +27 -0
- data/lib/rubyless.rb +1 -14
- data/rails/init.rb +1 -0
- data/rubyless.gemspec +56 -13
- data/test/RubyLess/active_record.yml +4 -4
- data/test/RubyLess/basic.yml +56 -18
- data/test/RubyLess/errors.yml +11 -11
- data/test/RubyLess/string.yml +11 -0
- data/test/RubyLess_test.rb +54 -20
- data/test/mock/dummy_class.rb +28 -3
- data/test/mock/dummy_module.rb +8 -0
- data/test/mock/property_column.rb +21 -0
- data/test/safe_class_test.rb +16 -0
- data/test/signature_hash_test.rb +44 -0
- data/test/test_helper.rb +3 -1
- metadata +76 -39
- data/lib/basic_types.rb +0 -15
@@ -26,14 +26,14 @@ module RubyLess
|
|
26
26
|
|
27
27
|
# Condition that could yield a nil result in the whole expression.
|
28
28
|
# For example in the following expression:
|
29
|
-
#
|
30
|
-
# "
|
29
|
+
# node.spouse.name == ''
|
30
|
+
# "node.spouse" would be the condition that could yield 'nil'.
|
31
31
|
def cond
|
32
32
|
@opts[:cond]
|
33
33
|
end
|
34
34
|
|
35
35
|
# raw result without nil checking:
|
36
|
-
# "
|
36
|
+
# "node.spouse.name" instead of "(node.spouse ? node.spouse.name : nil)"
|
37
37
|
def raw
|
38
38
|
@opts[:raw] || self.to_s
|
39
39
|
end
|
data/lib/ruby_less.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
=begin rdoc
|
2
|
+
=end
|
3
|
+
require 'ruby_less/info'
|
4
|
+
require 'ruby_less/basic_types'
|
5
|
+
require 'ruby_less/signature_hash'
|
6
|
+
require 'ruby_less/error'
|
7
|
+
require 'ruby_less/no_method_error'
|
8
|
+
require 'ruby_less/syntax_error'
|
9
|
+
require 'ruby_less/typed_string'
|
10
|
+
require 'ruby_less/safe_class'
|
11
|
+
require 'ruby_less/processor'
|
12
|
+
|
13
|
+
module RubyLess
|
14
|
+
def self.translate(string, helper)
|
15
|
+
RubyLessProcessor.translate(string, helper)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.translate_string(string, helper)
|
19
|
+
if string =~ /\#\{/
|
20
|
+
::RubyLess.translate("%Q{#{string}}", helper)
|
21
|
+
else
|
22
|
+
string.inspect
|
23
|
+
end
|
24
|
+
rescue => err
|
25
|
+
raise ::RubyLess::Error.new("Error parsing string \"#{string}\": #{err.message.strip}")
|
26
|
+
end
|
27
|
+
end
|
data/lib/rubyless.rb
CHANGED
@@ -1,14 +1 @@
|
|
1
|
-
|
2
|
-
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
-
|
4
|
-
require 'processor'
|
5
|
-
|
6
|
-
=begin rdoc
|
7
|
-
=end
|
8
|
-
module RubyLess
|
9
|
-
VERSION = '0.3.5'
|
10
|
-
|
11
|
-
def self.translate(string, helper)
|
12
|
-
RubyLessProcessor.translate(string, helper)
|
13
|
-
end
|
14
|
-
end
|
1
|
+
require 'ruby_less'
|
data/rails/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'rubyless'
|
data/rubyless.gemspec
CHANGED
@@ -1,24 +1,66 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
1
4
|
# -*- encoding: utf-8 -*-
|
2
5
|
|
3
6
|
Gem::Specification.new do |s|
|
4
7
|
s.name = %q{rubyless}
|
5
|
-
s.version = "0.
|
8
|
+
s.version = "0.4.0"
|
6
9
|
|
7
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
11
|
s.authors = ["Gaspard Bucher"]
|
9
|
-
s.date = %q{
|
10
|
-
s.description = %q{RubyLess is an interpreter for "safe ruby". The idea is to transform some "unsafe" ruby code into safe, type checked
|
11
|
-
ruby, eventually rewriting some variables or methods.}
|
12
|
+
s.date = %q{2010-03-21}
|
13
|
+
s.description = %q{RubyLess is an interpreter for "safe ruby". The idea is to transform some "unsafe" ruby code into safe, type checked ruby, eventually rewriting some variables or methods.}
|
12
14
|
s.email = %q{gaspard@teti.ch}
|
13
|
-
s.extra_rdoc_files = [
|
14
|
-
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.rdoc"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".gitignore",
|
20
|
+
"History.txt",
|
21
|
+
"README.rdoc",
|
22
|
+
"Rakefile",
|
23
|
+
"lib/ruby_less.rb",
|
24
|
+
"lib/ruby_less/basic_types.rb",
|
25
|
+
"lib/ruby_less/error.rb",
|
26
|
+
"lib/ruby_less/info.rb",
|
27
|
+
"lib/ruby_less/no_method_error.rb",
|
28
|
+
"lib/ruby_less/processor.rb",
|
29
|
+
"lib/ruby_less/safe_class.rb",
|
30
|
+
"lib/ruby_less/signature_hash.rb",
|
31
|
+
"lib/ruby_less/syntax_error.rb",
|
32
|
+
"lib/ruby_less/typed_string.rb",
|
33
|
+
"lib/rubyless.rb",
|
34
|
+
"rails/init.rb",
|
35
|
+
"rubyless.gemspec",
|
36
|
+
"test/RubyLess/active_record.yml",
|
37
|
+
"test/RubyLess/basic.yml",
|
38
|
+
"test/RubyLess/errors.yml",
|
39
|
+
"test/RubyLess/string.yml",
|
40
|
+
"test/RubyLess_test.rb",
|
41
|
+
"test/mock/active_record_mock.rb",
|
42
|
+
"test/mock/dummy_class.rb",
|
43
|
+
"test/mock/dummy_module.rb",
|
44
|
+
"test/mock/property_column.rb",
|
45
|
+
"test/safe_class_test.rb",
|
46
|
+
"test/signature_hash_test.rb",
|
47
|
+
"test/test_helper.rb"
|
48
|
+
]
|
15
49
|
s.homepage = %q{http://zenadmin.org/546}
|
16
|
-
s.rdoc_options = ["--
|
50
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
17
51
|
s.require_paths = ["lib"]
|
18
|
-
s.
|
19
|
-
s.rubygems_version = %q{1.3.5}
|
52
|
+
s.rubygems_version = %q{1.3.6}
|
20
53
|
s.summary = %q{RubyLess is an interpreter for "safe ruby"}
|
21
|
-
s.test_files = [
|
54
|
+
s.test_files = [
|
55
|
+
"test/mock/active_record_mock.rb",
|
56
|
+
"test/mock/dummy_class.rb",
|
57
|
+
"test/mock/dummy_module.rb",
|
58
|
+
"test/mock/property_column.rb",
|
59
|
+
"test/RubyLess_test.rb",
|
60
|
+
"test/safe_class_test.rb",
|
61
|
+
"test/signature_hash_test.rb",
|
62
|
+
"test/test_helper.rb"
|
63
|
+
]
|
22
64
|
|
23
65
|
if s.respond_to? :specification_version then
|
24
66
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
@@ -27,18 +69,19 @@ ruby, eventually rewriting some variables or methods.}
|
|
27
69
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
70
|
s.add_runtime_dependency(%q<ruby_parser>, [">= 2.0.4"])
|
29
71
|
s.add_runtime_dependency(%q<sexp_processor>, [">= 3.0.1"])
|
30
|
-
s.add_development_dependency(%q<
|
72
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
31
73
|
s.add_development_dependency(%q<yamltest>, [">= 0.5.3"])
|
32
74
|
else
|
33
75
|
s.add_dependency(%q<ruby_parser>, [">= 2.0.4"])
|
34
76
|
s.add_dependency(%q<sexp_processor>, [">= 3.0.1"])
|
35
|
-
s.add_dependency(%q<
|
77
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
36
78
|
s.add_dependency(%q<yamltest>, [">= 0.5.3"])
|
37
79
|
end
|
38
80
|
else
|
39
81
|
s.add_dependency(%q<ruby_parser>, [">= 2.0.4"])
|
40
82
|
s.add_dependency(%q<sexp_processor>, [">= 3.0.1"])
|
41
|
-
s.add_dependency(%q<
|
83
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
42
84
|
s.add_dependency(%q<yamltest>, [">= 0.5.3"])
|
43
85
|
end
|
44
86
|
end
|
87
|
+
|
@@ -1,19 +1,19 @@
|
|
1
1
|
time_type_from_columns:
|
2
2
|
src: 'log_at.strftime("%Y")'
|
3
|
-
tem: "(
|
3
|
+
tem: "(node.log_at ? node.log_at.strftime(\"%Y\") : nil)"
|
4
4
|
|
5
5
|
text_type_from_columns:
|
6
6
|
src: 'birth.strftime(format)'
|
7
|
-
tem: "Date.parse('2009-06-02 18:44').strftime(
|
7
|
+
tem: "Date.parse('2009-06-02 18:44').strftime(node.format)"
|
8
8
|
res: '02.06.2009'
|
9
9
|
|
10
10
|
number_type_from_columns:
|
11
11
|
src: "age + 15"
|
12
|
-
tem: "(
|
12
|
+
tem: "(node.age+15)"
|
13
13
|
res: "20"
|
14
14
|
|
15
15
|
number_type_from_columns_no_default:
|
16
16
|
src: "friend_id + 15"
|
17
|
-
tem: "(
|
17
|
+
tem: "(node.friend_id ? (node.friend_id+15) : nil)"
|
18
18
|
res: ""
|
19
19
|
|
data/test/RubyLess/basic.yml
CHANGED
@@ -4,7 +4,7 @@ empty:
|
|
4
4
|
|
5
5
|
numbers:
|
6
6
|
src: "id > 45 and (3 > -id or 3+3)"
|
7
|
-
tem: "((
|
7
|
+
tem: "((node.zip>45) and ((3>-node.zip) or (3+3)))"
|
8
8
|
|
9
9
|
global_method:
|
10
10
|
src: "now.strftime('%Y')"
|
@@ -12,11 +12,11 @@ global_method:
|
|
12
12
|
|
13
13
|
dynamic_string:
|
14
14
|
src: "now.strftime(\"#{name}\")"
|
15
|
-
tem: "Time.now.strftime(\"#{
|
15
|
+
tem: "Time.now.strftime(\"#{node.name}\")"
|
16
16
|
|
17
17
|
dynamic_string_again:
|
18
18
|
src: "now.strftime(\"#{name}\")"
|
19
|
-
tem: "Time.now.strftime(\"#{
|
19
|
+
tem: "Time.now.strftime(\"#{node.name}\")"
|
20
20
|
|
21
21
|
symbol:
|
22
22
|
src: ":foobar"
|
@@ -28,34 +28,34 @@ hash_access:
|
|
28
28
|
|
29
29
|
rewrite_variables:
|
30
30
|
src: "!prev.ancestor?(main) && !node.ancestor?(main)"
|
31
|
-
tem: "(not previous.ancestor?(@node) and not
|
31
|
+
tem: "(not previous.ancestor?(@node) and not node.ancestor?(@node))"
|
32
32
|
|
33
33
|
method_can_return_nil:
|
34
34
|
src: "spouse.name"
|
35
|
-
tem: "(
|
35
|
+
tem: "(node.spouse ? node.spouse.name : nil)"
|
36
36
|
|
37
37
|
method_on_method_can_return_nil:
|
38
38
|
src: "spouse.name == 'yo'"
|
39
|
-
tem: "(
|
39
|
+
tem: "(node.spouse ? (node.spouse.name==\"yo\") : nil)"
|
40
40
|
res: ""
|
41
41
|
|
42
42
|
nil_greater_then:
|
43
43
|
src: "spouse.id > 1"
|
44
|
-
tem: "(
|
44
|
+
tem: "(node.spouse ? (node.spouse.zip>1) : nil)"
|
45
45
|
|
46
46
|
nil_ternary_op:
|
47
47
|
src: "spouse ? 'foo' : 'bar'"
|
48
|
-
tem: "
|
48
|
+
tem: "node.spouse ? \"foo\" : \"bar\""
|
49
49
|
res: 'bar'
|
50
50
|
|
51
51
|
nested_ternary_op:
|
52
52
|
src: "spouse.name == 'Adam' ? 'man' : 'not a man'"
|
53
|
-
tem: "(
|
53
|
+
tem: "(node.spouse ? (node.spouse.name==\"Adam\") : nil) ? \"man\" : \"not a man\""
|
54
54
|
res: "not a man"
|
55
55
|
|
56
56
|
method_on_method:
|
57
57
|
src: "project.name.to_s"
|
58
|
-
tem: "
|
58
|
+
tem: "node.project.name.to_s"
|
59
59
|
res: 'project'
|
60
60
|
|
61
61
|
comp_ternary_op:
|
@@ -65,24 +65,24 @@ comp_ternary_op:
|
|
65
65
|
|
66
66
|
method_ternary_op:
|
67
67
|
src: "id > 2 ? 'foo' : 'bar'"
|
68
|
-
tem: "(
|
68
|
+
tem: "(node.zip>2) ? \"foo\" : \"bar\""
|
69
69
|
res: "foo"
|
70
70
|
|
71
71
|
method_argument_can_be_nil:
|
72
72
|
src: "vowel_count(spouse.name)"
|
73
|
-
tem: "(
|
73
|
+
tem: "(node.spouse ? vowel_count(node.spouse.name) : nil)"
|
74
74
|
|
75
75
|
multi_arg_method_argument_can_be_nil:
|
76
76
|
src: "log_info(spouse, 'foobar')"
|
77
|
-
tem: "(
|
77
|
+
tem: "(node.spouse ? log_info(node.spouse, \"foobar\") : nil)"
|
78
78
|
|
79
79
|
multi_arg_method_arguments_can_be_nil:
|
80
80
|
src: "log_info(husband, spouse.name)"
|
81
|
-
tem: "((
|
81
|
+
tem: "((node.husband && node.spouse) ? log_info(node.husband, node.spouse.name) : nil)"
|
82
82
|
|
83
83
|
multi_arg_method_arguments_can_be_nil_same_condition:
|
84
84
|
src: "log_info(spouse, spouse.name)"
|
85
|
-
tem: "(
|
85
|
+
tem: "(node.spouse ? log_info(node.spouse, node.spouse.name) : nil)"
|
86
86
|
|
87
87
|
literal_argument_for_method:
|
88
88
|
src: "vowel_count('ruby')"
|
@@ -94,10 +94,48 @@ safe_method_defined_as_symbol:
|
|
94
94
|
|
95
95
|
optional_arguments:
|
96
96
|
src: "width(:mode => 'pv')"
|
97
|
-
tem: "
|
97
|
+
tem: "node.width({:mode => \"pv\"})"
|
98
98
|
res: "mode: pv, type: none"
|
99
99
|
|
100
|
+
optional_arguments:
|
101
|
+
src: "width"
|
102
|
+
tem: "node.width"
|
103
|
+
res: "mode: none, type: none"
|
104
|
+
|
100
105
|
optional_arguments_string:
|
101
106
|
src: "width('nice' => 1 == 1)"
|
102
|
-
tem: "
|
103
|
-
res: "nice!"
|
107
|
+
tem: "node.width({\"nice\" => (1==1)})"
|
108
|
+
res: "nice!"
|
109
|
+
|
110
|
+
module_method:
|
111
|
+
src: "maze"
|
112
|
+
tem: "node.mazette"
|
113
|
+
res: "Mazette !"
|
114
|
+
|
115
|
+
regexp:
|
116
|
+
src: "maze.gsub(/ette/,'o')"
|
117
|
+
tem: "node.mazette.gsub(/ette/, \"o\")"
|
118
|
+
res: "Mazo !"
|
119
|
+
|
120
|
+
instance_variable:
|
121
|
+
src: "@foo.maze"
|
122
|
+
tem: "node.mazette"
|
123
|
+
res: "Mazette !"
|
124
|
+
|
125
|
+
prepend_arg:
|
126
|
+
src: "prepend_test(4)"
|
127
|
+
tem: "add(10, 4)"
|
128
|
+
res: "14"
|
129
|
+
|
130
|
+
safe_property:
|
131
|
+
src: "dog_name"
|
132
|
+
tem: "node.prop['dog_name']"
|
133
|
+
res: "Biscotte"
|
134
|
+
|
135
|
+
match_on_subclass:
|
136
|
+
src: "log_info(sub, 'hello')"
|
137
|
+
tem: "log_info(sub, \"hello\")"
|
138
|
+
|
139
|
+
optional_argument_subclass:
|
140
|
+
src: "width(:mode => str)"
|
141
|
+
tem: "node.width({:mode => str})"
|
data/test/RubyLess/errors.yml
CHANGED
@@ -1,39 +1,39 @@
|
|
1
1
|
unknown_global_method:
|
2
2
|
src: "system('echo date')"
|
3
|
-
res: "
|
3
|
+
res: "(RubyLessTest): unknown method 'system(String)'."
|
4
4
|
|
5
5
|
bad_argument_types:
|
6
6
|
src: "strftime(34,'ffoo')"
|
7
|
-
res: "
|
7
|
+
res: "(RubyLessTest): unknown method 'strftime(Number, String)'."
|
8
8
|
|
9
9
|
zero_div:
|
10
10
|
src: "1/(id-10)"
|
11
|
-
tem: "(1/(
|
11
|
+
tem: "(1/(node.zip-10) rescue nil)"
|
12
12
|
res: ""
|
13
13
|
|
14
14
|
looping:
|
15
15
|
src: "while(true) do puts 'flood' end"
|
16
|
-
res: '
|
16
|
+
res: "'while' not available in RubyLess."
|
17
17
|
|
18
18
|
add_two_strings:
|
19
19
|
src: "name + 14"
|
20
|
-
res: "
|
20
|
+
res: "node.name (String): unknown method '+(Number)'."
|
21
21
|
|
22
22
|
two_arguments_in_hash:
|
23
23
|
src: "dictionary[:one, :two]"
|
24
|
-
res: "
|
24
|
+
res: "get_dict (StringDictionary): unknown method '[](Symbol, Symbol)'."
|
25
25
|
|
26
26
|
number_argument:
|
27
27
|
src: "dictionary[43]"
|
28
|
-
res: "
|
28
|
+
res: "get_dict (StringDictionary): unknown method '[](Number)'."
|
29
29
|
|
30
30
|
string_argument:
|
31
31
|
src: "dictionary[spouse.name]"
|
32
|
-
res: "
|
32
|
+
res: "get_dict (StringDictionary): unknown method '[](String)'."
|
33
33
|
|
34
34
|
symbol_type_not_used_out_of_helper:
|
35
35
|
src: "node.foo"
|
36
|
-
tem: "
|
36
|
+
tem: "node (Dummy): unknown method 'foo()'."
|
37
37
|
|
38
38
|
optional_arguments_with_dynamic_string:
|
39
39
|
src: "spouse.width(\"nice#{spouse.name}\" => 'pv')"
|
@@ -42,8 +42,8 @@ optional_arguments_with_dynamic_string:
|
|
42
42
|
|
43
43
|
optional_arguments_bad_type:
|
44
44
|
src: "width(:mode => 12)"
|
45
|
-
res: "
|
45
|
+
res: "(RubyLessTest): unknown method 'width(:mode=>Number)'."
|
46
46
|
|
47
47
|
optional_arguments_bad_argument:
|
48
48
|
src: "width(:xyz => 'pv')"
|
49
|
-
res: "
|
49
|
+
res: "(RubyLessTest): unknown method 'width(:xyz=>String)'."
|
data/test/RubyLess_test.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'date'
|
2
|
-
require
|
2
|
+
require 'test_helper'
|
3
3
|
|
4
4
|
class StringDictionary
|
5
5
|
include RubyLess::SafeClass
|
@@ -7,6 +7,10 @@ class StringDictionary
|
|
7
7
|
disable_safe_read
|
8
8
|
end
|
9
9
|
|
10
|
+
# Used to test sub-classes in optional arguments
|
11
|
+
class SubString < String
|
12
|
+
end
|
13
|
+
|
10
14
|
class RubyLessTest < Test::Unit::TestCase
|
11
15
|
attr_reader :context
|
12
16
|
yamltest :src_from_title => false
|
@@ -22,13 +26,19 @@ class RubyLessTest < Test::Unit::TestCase
|
|
22
26
|
safe_method :foo => :contextual_method, :bar => :contextual_method
|
23
27
|
safe_method_for String, [:==, String] => Boolean
|
24
28
|
safe_method_for String, [:to_s] => String
|
29
|
+
safe_method_for String, [:gsub, Regexp, String] => String
|
25
30
|
safe_method_for Time, [:strftime, String] => String
|
31
|
+
safe_method :@foo => {:class => Dummy, :method => "node"}
|
32
|
+
safe_method :sub => SubDummy
|
33
|
+
safe_method :str => SubString
|
26
34
|
|
27
35
|
# Example to dynamically rewrite method calls during compilation
|
28
36
|
def safe_method_type(signature)
|
29
37
|
unless res = super
|
30
|
-
|
31
|
-
|
38
|
+
if signature == ['prepend_test', Number]
|
39
|
+
res ={:class => Number, :prepend_args => RubyLess::TypedString.new('10', :class => Number), :method => 'add'}
|
40
|
+
elsif res = context[:node_class].safe_method_type(signature)
|
41
|
+
# try to execute method in the current var "var.method"
|
32
42
|
res = res.call(self, signature) if res.kind_of?(Proc)
|
33
43
|
res = res.merge(:method => "#{context[:node]}.#{res[:method] || signature[0]}")
|
34
44
|
end
|
@@ -40,10 +50,22 @@ class RubyLessTest < Test::Unit::TestCase
|
|
40
50
|
{:method => "contextual_#{signature[0]}", :class => String}
|
41
51
|
end
|
42
52
|
|
43
|
-
def
|
53
|
+
def node
|
44
54
|
Dummy.new
|
45
55
|
end
|
46
56
|
|
57
|
+
def sub
|
58
|
+
SubDummy.new
|
59
|
+
end
|
60
|
+
|
61
|
+
def str
|
62
|
+
"str"
|
63
|
+
end
|
64
|
+
|
65
|
+
def add(a,b)
|
66
|
+
a+b
|
67
|
+
end
|
68
|
+
|
47
69
|
def vowel_count(str)
|
48
70
|
str.tr('^aeiouy', '').size
|
49
71
|
end
|
@@ -70,28 +92,40 @@ class RubyLessTest < Test::Unit::TestCase
|
|
70
92
|
|
71
93
|
def yt_do_test(file, test, context = yt_get('context',file,test))
|
72
94
|
@@test_strings[file][test].keys.each do |key|
|
73
|
-
next if ['src', 'context'].include?(key)
|
95
|
+
next if ['src', 'context', 'str'].include?(key)
|
74
96
|
yt_assert yt_get(key,file,test), parse(key, file, test, context)
|
75
97
|
end
|
76
98
|
end
|
77
99
|
|
78
100
|
def parse(key, file, test, opts)
|
79
|
-
@context = {:node => '
|
80
|
-
source = yt_get('
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
101
|
+
@context = {:node => 'node', :node_class => Dummy}
|
102
|
+
if source = yt_get('str', file, test)
|
103
|
+
case key
|
104
|
+
when 'tem'
|
105
|
+
source ? RubyLess.translate_string(source, self) : yt_get('tem', file, test)
|
106
|
+
when 'res'
|
107
|
+
eval(source ? RubyLess.translate_string(source, self) : yt_get('tem', file, test)).to_s
|
108
|
+
when 'sxp'
|
109
|
+
RubyParser.new.parse(source).inspect
|
110
|
+
else
|
111
|
+
"Unknown key '#{key}'. Should be 'tem' or 'res'."
|
112
|
+
end
|
113
|
+
elsif source = yt_get('src', file, test)
|
114
|
+
case key
|
115
|
+
when 'tem'
|
116
|
+
source ? RubyLess.translate(source, self) : yt_get('tem', file, test)
|
117
|
+
when 'res'
|
118
|
+
res = RubyLess.translate(source, self)
|
119
|
+
eval(source ? RubyLess.translate(source, self) : yt_get('tem', file, test)).to_s
|
120
|
+
when 'sxp'
|
121
|
+
RubyParser.new.parse(source).inspect
|
122
|
+
else
|
123
|
+
"Unknown key '#{key}'. Should be 'tem' or 'res'."
|
124
|
+
end
|
91
125
|
end
|
92
|
-
rescue => err
|
93
|
-
#puts "\n\n#{err.message}"
|
94
|
-
#puts err.backtrace
|
126
|
+
rescue RubyLess::Error => err
|
127
|
+
# puts "\n\n#{err.message}"
|
128
|
+
# puts err.backtrace
|
95
129
|
err.message
|
96
130
|
end
|
97
131
|
|
data/test/mock/dummy_class.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/active_record_mock'
|
2
|
+
require File.dirname(__FILE__) + '/dummy_module'
|
3
|
+
require File.dirname(__FILE__) + '/property_column'
|
2
4
|
|
3
5
|
class Dummy < RubyLess::ActiveRecordMock
|
4
|
-
|
6
|
+
include DummyModule
|
5
7
|
include RubyLess::SafeClass
|
6
8
|
|
9
|
+
attr_reader :name
|
10
|
+
|
7
11
|
safe_method [:ancestor?, Dummy] => Boolean
|
8
12
|
safe_method :parent => {:class => 'Dummy', :special_option => 'foobar'},
|
9
13
|
:children => ['Dummy'],
|
@@ -12,7 +16,8 @@ class Dummy < RubyLess::ActiveRecordMock
|
|
12
16
|
:id => {:class => Number, :method => :zip},
|
13
17
|
:name => String,
|
14
18
|
:foo => :bar,
|
15
|
-
[:width, {:mode => String, :type => String, 'nice' => Boolean}]
|
19
|
+
[:width, {:mode => String, :type => String, 'nice' => Boolean}] => String,
|
20
|
+
[:width] => String
|
16
21
|
safe_context :spouse => 'Dummy',
|
17
22
|
:husband => {:class => 'Dummy', :context => {:clever => 'no'}}
|
18
23
|
|
@@ -22,6 +27,23 @@ class Dummy < RubyLess::ActiveRecordMock
|
|
22
27
|
@name = name
|
23
28
|
end
|
24
29
|
|
30
|
+
# Mock Property ================= [
|
31
|
+
def self.schema; self; end
|
32
|
+
def self.columns
|
33
|
+
{
|
34
|
+
'dog_name' => MockPropertyColumn.new('dog_name', nil, :string),
|
35
|
+
'dog_age' => MockPropertyColumn.new('dog_age', 0, :number),
|
36
|
+
}
|
37
|
+
end
|
38
|
+
def prop
|
39
|
+
{
|
40
|
+
'dog_name' => 'Biscotte',
|
41
|
+
'dog_age' => 6,
|
42
|
+
}
|
43
|
+
end
|
44
|
+
# Mock Property ================= ]
|
45
|
+
safe_property :dog_name, :dog_age
|
46
|
+
|
25
47
|
def width(opts = {})
|
26
48
|
return 'nice!' if opts['nice']
|
27
49
|
"mode: #{(opts[:mode] || 'none')}, type: #{(opts[:type] || 'none')}"
|
@@ -48,4 +70,7 @@ class Dummy < RubyLess::ActiveRecordMock
|
|
48
70
|
def zip
|
49
71
|
10
|
50
72
|
end
|
51
|
-
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class SubDummy < Dummy
|
76
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class MockPropertyColumn
|
2
|
+
attr_reader :name, :default, :klass
|
3
|
+
def initialize(name, default, type)
|
4
|
+
case type
|
5
|
+
when :string
|
6
|
+
@klass = String
|
7
|
+
when :number
|
8
|
+
@klass = Number
|
9
|
+
end
|
10
|
+
@name = name
|
11
|
+
@default = default
|
12
|
+
end
|
13
|
+
|
14
|
+
def number?
|
15
|
+
@klass == Number
|
16
|
+
end
|
17
|
+
|
18
|
+
def text?
|
19
|
+
@klass == String
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class SafeClassTest < Test::Unit::TestCase
|
4
|
+
class SubString < String
|
5
|
+
end
|
6
|
+
|
7
|
+
context 'A safe model' do
|
8
|
+
subject do
|
9
|
+
Dummy
|
10
|
+
end
|
11
|
+
|
12
|
+
should 'have an associated SignatureHash for safe methods' do
|
13
|
+
assert_kind_of RubyLess::SignatureHash, Dummy.safe_methods
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|