testml 0.0.1 → 0.0.2
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/.gemspec +3 -1
- data/CHANGELOG.yaml +4 -1
- data/LICENSE +1 -1
- data/README.rdoc +30 -5
- data/Rakefile +10 -1
- data/ToDo +56 -0
- data/lib/rake/testml.rb +14 -0
- data/lib/testml.rb +46 -2
- data/lib/testml/bridge.rb +5 -0
- data/lib/testml/compiler.rb +106 -0
- data/lib/testml/compiler/lite.rb +194 -0
- data/lib/testml/compiler/pegex.rb +50 -0
- data/lib/testml/compiler/pegex/ast.rb +145 -0
- data/lib/testml/compiler/pegex/grammar.rb +173 -0
- data/lib/testml/library.rb +7 -0
- data/lib/testml/library/debug.rb +18 -0
- data/lib/testml/library/standard.rb +86 -0
- data/lib/testml/runtime.rb +501 -0
- data/lib/testml/runtime/unit.rb +94 -0
- data/lib/testml/setup.rb +65 -0
- data/lib/testml/util.rb +22 -0
- data/test/ast/arguments.tml +87 -0
- data/test/ast/basic.tml +83 -0
- data/test/ast/dataless.tml +36 -0
- data/test/ast/exceptions.tml +59 -0
- data/test/ast/external.tml +42 -0
- data/test/ast/function.tml +276 -0
- data/test/ast/label.tml +58 -0
- data/test/ast/markers.tml +36 -0
- data/test/ast/semicolons.tml +30 -0
- data/test/ast/truth.tml +85 -0
- data/test/ast/types.tml +163 -0
- data/test/compile-lite.rb +38 -0
- data/test/compile-testml-document.rb +59 -0
- data/test/compile.rb +57 -0
- data/test/inline-bridge.rb +30 -0
- data/test/inline.rb +28 -0
- data/test/strings.rb +24 -0
- data/test/testml.rb +38 -0
- data/test/testml.yaml +10 -0
- data/test/testml/arguments.tml +18 -0
- data/test/testml/assertions.tml +15 -0
- data/test/testml/basic.tml +37 -0
- data/test/testml/dataless.tml +9 -0
- data/test/testml/exceptions.tml +16 -0
- data/test/testml/external.tml +8 -0
- data/test/testml/external1.tml +10 -0
- data/test/testml/external2.tml +3 -0
- data/test/testml/function.tml +82 -0
- data/test/testml/label.tml +24 -0
- data/test/testml/markers.tml +19 -0
- data/test/testml/semicolons.tml +10 -0
- data/test/testml/standard.tml +50 -0
- data/test/testml/truth.tml +22 -0
- data/test/testml/types.tml +24 -0
- data/test/testml_bridge.rb +28 -0
- metadata +69 -4
- data/test/fail.rb +0 -12
data/test/ast/types.tml
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
--- !!perl/hash:TestML::Function
|
2
|
+
namespace:
|
3
|
+
TestML: !!perl/hash:TestML::Str
|
4
|
+
value: '0.1.0'
|
5
|
+
|
6
|
+
statements:
|
7
|
+
- !!perl/hash:TestML::Assignment
|
8
|
+
name: Plan
|
9
|
+
expr: !!perl/hash:TestML::Num
|
10
|
+
value: 11
|
11
|
+
- !!perl/hash:TestML::Assignment
|
12
|
+
name: Label
|
13
|
+
expr: !!perl/hash:TestML::Str
|
14
|
+
value: Test $TestNumber
|
15
|
+
- !!perl/hash:TestML::Statement
|
16
|
+
expr: !!perl/hash:TestML::Expression
|
17
|
+
calls:
|
18
|
+
- !!perl/hash:TestML::Str
|
19
|
+
value: Foo
|
20
|
+
- !!perl/hash:TestML::Call
|
21
|
+
name: Type
|
22
|
+
assert: !!perl/hash:TestML::Assertion
|
23
|
+
name: EQ
|
24
|
+
expr: !!perl/hash:TestML::Str
|
25
|
+
value: Str
|
26
|
+
- !!perl/hash:TestML::Statement
|
27
|
+
expr: !!perl/hash:TestML::Expression
|
28
|
+
calls:
|
29
|
+
- !!perl/hash:TestML::Num
|
30
|
+
value: 42
|
31
|
+
- !!perl/hash:TestML::Call
|
32
|
+
name: Type
|
33
|
+
assert: !!perl/hash:TestML::Assertion
|
34
|
+
name: EQ
|
35
|
+
expr: !!perl/hash:TestML::Str
|
36
|
+
value: Num
|
37
|
+
- !!perl/hash:TestML::Statement
|
38
|
+
expr: !!perl/hash:TestML::Expression
|
39
|
+
calls:
|
40
|
+
- !!perl/hash:TestML::Call
|
41
|
+
name: 'True'
|
42
|
+
- !!perl/hash:TestML::Call
|
43
|
+
name: Type
|
44
|
+
assert: !!perl/hash:TestML::Assertion
|
45
|
+
name: EQ
|
46
|
+
expr: !!perl/hash:TestML::Str
|
47
|
+
value: Bool
|
48
|
+
- !!perl/hash:TestML::Statement
|
49
|
+
expr: !!perl/hash:TestML::Expression
|
50
|
+
calls:
|
51
|
+
- !!perl/hash:TestML::Call
|
52
|
+
args:
|
53
|
+
- !!perl/hash:TestML::Num
|
54
|
+
value: 1
|
55
|
+
- !!perl/hash:TestML::Num
|
56
|
+
value: 2
|
57
|
+
- !!perl/hash:TestML::Num
|
58
|
+
value: 3
|
59
|
+
name: List
|
60
|
+
- !!perl/hash:TestML::Call
|
61
|
+
name: Type
|
62
|
+
assert: !!perl/hash:TestML::Assertion
|
63
|
+
name: EQ
|
64
|
+
expr: !!perl/hash:TestML::Str
|
65
|
+
value: List
|
66
|
+
- !!perl/hash:TestML::Statement
|
67
|
+
expr: !!perl/hash:TestML::Expression
|
68
|
+
calls:
|
69
|
+
- !!perl/hash:TestML::Function
|
70
|
+
statements: []
|
71
|
+
- !!perl/hash:TestML::Call
|
72
|
+
name: Type
|
73
|
+
assert: !!perl/hash:TestML::Assertion
|
74
|
+
name: EQ
|
75
|
+
expr: !!perl/hash:TestML::Str
|
76
|
+
value: Func
|
77
|
+
- !!perl/hash:TestML::Statement
|
78
|
+
expr: !!perl/hash:TestML::Expression
|
79
|
+
calls:
|
80
|
+
- !!perl/hash:TestML::Function
|
81
|
+
statements: []
|
82
|
+
- !!perl/hash:TestML::Call
|
83
|
+
name: Type
|
84
|
+
assert: !!perl/hash:TestML::Assertion
|
85
|
+
name: EQ
|
86
|
+
expr: !!perl/hash:TestML::Str
|
87
|
+
value: Func
|
88
|
+
- !!perl/hash:TestML::Assignment
|
89
|
+
name: s
|
90
|
+
expr: !!perl/hash:TestML::Str
|
91
|
+
value: Foo
|
92
|
+
- !!perl/hash:TestML::Statement
|
93
|
+
expr: !!perl/hash:TestML::Expression
|
94
|
+
calls:
|
95
|
+
- !!perl/hash:TestML::Call
|
96
|
+
name: s
|
97
|
+
- !!perl/hash:TestML::Call
|
98
|
+
name: Type
|
99
|
+
assert: !!perl/hash:TestML::Assertion
|
100
|
+
name: EQ
|
101
|
+
expr: !!perl/hash:TestML::Str
|
102
|
+
value: Str
|
103
|
+
- !!perl/hash:TestML::Assignment
|
104
|
+
name: n
|
105
|
+
expr: !!perl/hash:TestML::Num
|
106
|
+
value: 42
|
107
|
+
- !!perl/hash:TestML::Statement
|
108
|
+
expr: !!perl/hash:TestML::Expression
|
109
|
+
calls:
|
110
|
+
- !!perl/hash:TestML::Call
|
111
|
+
name: n
|
112
|
+
- !!perl/hash:TestML::Call
|
113
|
+
name: Type
|
114
|
+
assert: !!perl/hash:TestML::Assertion
|
115
|
+
name: EQ
|
116
|
+
expr: !!perl/hash:TestML::Str
|
117
|
+
value: Num
|
118
|
+
- !!perl/hash:TestML::Assignment
|
119
|
+
name: b
|
120
|
+
expr: !!perl/hash:TestML::Call
|
121
|
+
name: 'False'
|
122
|
+
- !!perl/hash:TestML::Statement
|
123
|
+
expr: !!perl/hash:TestML::Expression
|
124
|
+
calls:
|
125
|
+
- !!perl/hash:TestML::Call
|
126
|
+
name: b
|
127
|
+
- !!perl/hash:TestML::Call
|
128
|
+
name: Type
|
129
|
+
assert: !!perl/hash:TestML::Assertion
|
130
|
+
name: EQ
|
131
|
+
expr: !!perl/hash:TestML::Str
|
132
|
+
value: Bool
|
133
|
+
- !!perl/hash:TestML::Assignment
|
134
|
+
name: l
|
135
|
+
expr: !!perl/hash:TestML::Call
|
136
|
+
name: List
|
137
|
+
args: []
|
138
|
+
- !!perl/hash:TestML::Statement
|
139
|
+
expr: !!perl/hash:TestML::Expression
|
140
|
+
calls:
|
141
|
+
- !!perl/hash:TestML::Call
|
142
|
+
name: l
|
143
|
+
- !!perl/hash:TestML::Call
|
144
|
+
name: Type
|
145
|
+
assert: !!perl/hash:TestML::Assertion
|
146
|
+
name: EQ
|
147
|
+
expr: !!perl/hash:TestML::Str
|
148
|
+
value: List
|
149
|
+
- !!perl/hash:TestML::Assignment
|
150
|
+
name: f
|
151
|
+
expr: !!perl/hash:TestML::Function
|
152
|
+
statements: []
|
153
|
+
- !!perl/hash:TestML::Statement
|
154
|
+
expr: !!perl/hash:TestML::Expression
|
155
|
+
calls:
|
156
|
+
- !!perl/hash:TestML::Call
|
157
|
+
name: f
|
158
|
+
- !!perl/hash:TestML::Call
|
159
|
+
name: Type
|
160
|
+
assert: !!perl/hash:TestML::Assertion
|
161
|
+
name: EQ
|
162
|
+
expr: !!perl/hash:TestML::Str
|
163
|
+
value: Func
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'testml/runtime'
|
4
|
+
require 'testml/compiler/pegex'
|
5
|
+
require 'testml/compiler/lite'
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
class TestCompileLite < Test::Unit::TestCase
|
9
|
+
def test_compile_lite
|
10
|
+
testml = <<'...'
|
11
|
+
# A comment
|
12
|
+
%TestML 0.1.0
|
13
|
+
|
14
|
+
Plan = 2;
|
15
|
+
Title = "O HAI TEST";
|
16
|
+
|
17
|
+
*input.uppercase == *output;
|
18
|
+
|
19
|
+
=== Test mixed case string
|
20
|
+
--- input: I Like Pie
|
21
|
+
--- output: I LIKE PIE
|
22
|
+
|
23
|
+
=== Test lower case string
|
24
|
+
--- input: i love lucy
|
25
|
+
--- output: I LOVE LUCY
|
26
|
+
...
|
27
|
+
|
28
|
+
func = TestML::Compiler::Pegex.new.compile(testml)
|
29
|
+
func_lite = TestML::Compiler::Lite.new.compile(testml)
|
30
|
+
|
31
|
+
# File.open('/tmp/got', 'w') {|f| f.write func.to_yaml}
|
32
|
+
# File.open('/tmp/want', 'w') {|f| f.write func_lite.to_yaml}
|
33
|
+
# STDERR.write(`diff -u /tmp/want /tmp/got`)
|
34
|
+
|
35
|
+
assert_equal YAML.dump(func_lite), YAML.dump(func),
|
36
|
+
'Lite compile matches normal compile'
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'testml/runtime'
|
4
|
+
require 'testml/compiler/pegex'
|
5
|
+
|
6
|
+
class TestCompileTestMLDocument < Test::Unit::TestCase
|
7
|
+
def test_compile_testml_document
|
8
|
+
testml = <<'...'
|
9
|
+
# A comment
|
10
|
+
%TestML 0.1.0
|
11
|
+
|
12
|
+
Plan = 2
|
13
|
+
Title = "O HAI TEST"
|
14
|
+
|
15
|
+
*input.uppercase() == *output
|
16
|
+
|
17
|
+
=== Test mixed case string
|
18
|
+
--- input: I Like Pie
|
19
|
+
--- output: I LIKE PIE
|
20
|
+
|
21
|
+
=== Test lower case string
|
22
|
+
--- input: i love lucy
|
23
|
+
--- output: I LOVE LUCY
|
24
|
+
...
|
25
|
+
|
26
|
+
func = TestML::Compiler::Pegex.new.compile(testml)
|
27
|
+
assert func, 'TestML string matches against TestML grammar'
|
28
|
+
assert_equal func.namespace['TestML'].value, '0.1.0', 'Version parses'
|
29
|
+
assert_equal func.statements[0].expr.value, 2, 'Plan parses'
|
30
|
+
assert_equal func.statements[1].expr.value, 'O HAI TEST', 'Title parses'
|
31
|
+
assert_equal func.statements[1].expr.value, 'O HAI TEST', 'Title parses'
|
32
|
+
|
33
|
+
assert_equal func.statements.size, 3, 'Three test statements'
|
34
|
+
statement = func.statements[2]
|
35
|
+
assert_equal statement.points.join('-'), 'input-output',
|
36
|
+
'Point list is correct'
|
37
|
+
|
38
|
+
assert_equal statement.expr.calls.size, 2, 'Expression has two calls'
|
39
|
+
expr = statement.expr
|
40
|
+
assert expr.calls[0].kind_of?(TestML::Point), 'First sub is a Point'
|
41
|
+
assert_equal expr.calls[0].name, 'input', 'Point name is "input"'
|
42
|
+
assert_equal expr.calls[1].name, 'uppercase', 'Second sub is "uppercase"'
|
43
|
+
|
44
|
+
assert_equal statement.assert.name, 'EQ', 'Assertion is "EQ"'
|
45
|
+
|
46
|
+
expr = statement.assert.expr
|
47
|
+
assert expr.kind_of?(TestML::Point), 'First sub is a Point'
|
48
|
+
assert_equal expr.name, 'output', 'Point name is "output"'
|
49
|
+
|
50
|
+
assert_equal func.data.size, 2, 'Two data blocks'
|
51
|
+
(block1, block2) = func.data
|
52
|
+
assert_equal block1.label, 'Test mixed case string', 'Block 1 label ok'
|
53
|
+
assert_equal block1.points['input'], 'I Like Pie', 'Block 1, input point'
|
54
|
+
assert_equal block1.points['output'], 'I LIKE PIE', 'Block 1, output point'
|
55
|
+
assert_equal block2.label, 'Test lower case string', 'Block 2 label ok'
|
56
|
+
assert_equal block2.points['input'], 'i love lucy', 'Block 2, input point'
|
57
|
+
assert_equal block2.points['output'], 'I LOVE LUCY', 'Block 2, output point'
|
58
|
+
end
|
59
|
+
end
|
data/test/compile.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'testml/runtime'
|
4
|
+
require 'testml/compiler/lite'
|
5
|
+
require 'testml/compiler/pegex'
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
class TestCompile < Test::Unit::TestCase
|
9
|
+
def test_compile
|
10
|
+
compile('testml/arguments.tml', TestML::Compiler::Pegex)
|
11
|
+
compile('testml/basic.tml', TestML::Compiler::Pegex)
|
12
|
+
compile('testml/dataless.tml', TestML::Compiler::Pegex)
|
13
|
+
compile('testml/exceptions.tml', TestML::Compiler::Pegex)
|
14
|
+
compile('testml/external.tml', TestML::Compiler::Pegex)
|
15
|
+
compile('testml/function.tml', TestML::Compiler::Pegex)
|
16
|
+
compile('testml/label.tml', TestML::Compiler::Pegex)
|
17
|
+
compile('testml/markers.tml', TestML::Compiler::Pegex)
|
18
|
+
compile('testml/semicolons.tml', TestML::Compiler::Pegex)
|
19
|
+
compile('testml/truth.tml', TestML::Compiler::Pegex)
|
20
|
+
compile('testml/types.tml', TestML::Compiler::Pegex)
|
21
|
+
|
22
|
+
compile('testml/arguments.tml', TestML::Compiler::Lite)
|
23
|
+
compile('testml/basic.tml', TestML::Compiler::Lite)
|
24
|
+
compile('testml/exceptions.tml', TestML::Compiler::Lite)
|
25
|
+
compile('testml/semicolons.tml', TestML::Compiler::Lite)
|
26
|
+
end
|
27
|
+
|
28
|
+
def compile(file, compiler=TestML::Compiler)
|
29
|
+
filename = file.sub(/(.*)\//, '')
|
30
|
+
runtime = TestML::Runtime.new({base: "test/#{$1}"})
|
31
|
+
testml = runtime.read_testml_file(filename)
|
32
|
+
ast1 = compiler.new.compile(testml)
|
33
|
+
got = YAML.dump(ast1)
|
34
|
+
|
35
|
+
yaml = File.read("test/ast/#{filename}") \
|
36
|
+
.gsub(/!!perl\/hash:/, '!ruby/object:') \
|
37
|
+
.gsub(/(explicit_call: )(\d)/) do |m|
|
38
|
+
"#{$1}#{($2 == '1') ? 'true' : 'false'}"
|
39
|
+
end
|
40
|
+
# .gsub(/^(\s*):(\w+:)/, "$1$2")
|
41
|
+
|
42
|
+
ast2 = YAML.load(yaml)
|
43
|
+
want = YAML.dump(ast2)
|
44
|
+
|
45
|
+
label = "#{file} - #{compiler.to_s}"
|
46
|
+
if got == want
|
47
|
+
assert_equal want, got, label
|
48
|
+
else
|
49
|
+
puts "Failed test: #{label}"
|
50
|
+
if want.match /\n/
|
51
|
+
File.open('/tmp/got', 'w') {|f| f.write got}
|
52
|
+
File.open('/tmp/want', 'w') {|f| f.write want}
|
53
|
+
puts `diff -u /tmp/want /tmp/got`
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'testml'
|
2
|
+
require 'testml/bridge'
|
3
|
+
require 'testml/util'
|
4
|
+
include TestML::Util
|
5
|
+
|
6
|
+
class Bridge < TestML::Bridge
|
7
|
+
def upper(string)
|
8
|
+
str string.value.upcase
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
TestML.new(
|
13
|
+
bridge: Bridge,
|
14
|
+
).testml = <<'...'
|
15
|
+
%TestML 0.1.0
|
16
|
+
|
17
|
+
*foo.upper() == *bar
|
18
|
+
|
19
|
+
=== Foo for thought
|
20
|
+
--- foo: o hai
|
21
|
+
--- bar: O HAI
|
22
|
+
|
23
|
+
=== Bar the door
|
24
|
+
--- foo
|
25
|
+
o
|
26
|
+
Hai
|
27
|
+
--- bar
|
28
|
+
O
|
29
|
+
HAI
|
30
|
+
...
|
data/test/inline.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
$:.unshift "#{Dir.getwd}/test"
|
2
|
+
|
3
|
+
require 'testml'
|
4
|
+
require 'testml_bridge'
|
5
|
+
|
6
|
+
TestML.new(
|
7
|
+
bridge: TestMLBridge,
|
8
|
+
).testml = <<'...'
|
9
|
+
%TestML 0.1.0
|
10
|
+
|
11
|
+
Title = "Ingy's Test";
|
12
|
+
Plan = 4;
|
13
|
+
|
14
|
+
*foo == *bar;
|
15
|
+
*bar == *foo;
|
16
|
+
|
17
|
+
=== Foo for thought
|
18
|
+
--- foo: O HAI
|
19
|
+
--- bar: O HAI
|
20
|
+
|
21
|
+
=== Bar the door
|
22
|
+
--- bar
|
23
|
+
O
|
24
|
+
HAI
|
25
|
+
--- foo
|
26
|
+
O
|
27
|
+
HAI
|
28
|
+
...
|
data/test/strings.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'testml'
|
2
|
+
|
3
|
+
TestML.new.testml = <<'...'
|
4
|
+
%TestML 0.1.0
|
5
|
+
|
6
|
+
Plan = 6
|
7
|
+
|
8
|
+
Throw(*error).bogus().Catch() == *error
|
9
|
+
*error.Throw().bogus().Catch() == *error
|
10
|
+
Throw('My error message').Catch() == *error
|
11
|
+
|
12
|
+
*empty == "".Str
|
13
|
+
*empty == ""
|
14
|
+
|
15
|
+
Label = 'Simple string comparison'
|
16
|
+
"foo" == "foo"
|
17
|
+
|
18
|
+
=== Throw/Catch
|
19
|
+
--- error: My error message
|
20
|
+
|
21
|
+
=== Empty Point
|
22
|
+
--- empty
|
23
|
+
|
24
|
+
...
|
data/test/testml.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'testml'
|
3
|
+
require 'testml/compiler/pegex'
|
4
|
+
require 'testml/compiler/lite'
|
5
|
+
$:.unshift "#{Dir.getwd}/test"
|
6
|
+
require 'testml_bridge'
|
7
|
+
|
8
|
+
class TestMLTestCase < Test::Unit::TestCase
|
9
|
+
def run_testml_file(file, compiler=TestML::Compiler::Pegex)
|
10
|
+
TestML.new(
|
11
|
+
testml: file,
|
12
|
+
bridge: TestMLBridge,
|
13
|
+
compiler: compiler,
|
14
|
+
).run(self)
|
15
|
+
end
|
16
|
+
|
17
|
+
(Dir.glob('test/testml/*.tml')
|
18
|
+
.select { |f| f !~ /external[12]/ }
|
19
|
+
.collect {|f| f.sub(/^test\//, '')}
|
20
|
+
).each do |file|
|
21
|
+
method_name = 'test_' + file.gsub(/\W/, '_').sub(/_tml$/, '')
|
22
|
+
define_method(method_name.to_sym) do
|
23
|
+
run_testml_file(file)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
%w(
|
28
|
+
testml/arguments.tml
|
29
|
+
testml/basic.tml
|
30
|
+
testml/exceptions.tml
|
31
|
+
testml/semicolons.tml
|
32
|
+
).each do |file|
|
33
|
+
method_name = 'test_lite_' + file.gsub(/\W/, '_').sub(/_tml$/, '')
|
34
|
+
define_method(method_name.to_sym) do
|
35
|
+
run_testml_file(file, TestML::Compiler::Lite)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|