petri_net 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.
- checksums.yaml +7 -0
- data/.ruby-version +1 -0
- data/CHANGELOG +8 -0
- data/LICENSE +21 -0
- data/README.rdoc +93 -0
- data/Rakefile +30 -0
- data/lib/petri_net/arc.rb +133 -0
- data/lib/petri_net/base.rb +28 -0
- data/lib/petri_net/edge.rb +38 -0
- data/lib/petri_net/marking.rb +28 -0
- data/lib/petri_net/net.rb +314 -0
- data/lib/petri_net/node.rb +44 -0
- data/lib/petri_net/place.rb +108 -0
- data/lib/petri_net/reachability_graph.rb +93 -0
- data/lib/petri_net/transition.rb +109 -0
- data/lib/petri_net.rb +35 -0
- data/test/create.rb +64 -0
- data/test/tc_arc.rb +0 -0
- data/test/tc_edge.rb +0 -0
- data/test/tc_graph.rb +0 -0
- data/test/tc_node.rb +0 -0
- data/test/tc_petri_net.rb +320 -0
- data/test/tc_place.rb +0 -0
- data/test/tc_transition.rb +6 -0
- data/test/ts_test_all.rb +2 -0
- metadata +78 -0
data/test/create.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'logger'
|
5
|
+
require "#{`pwd`.strip}/../lib/petri_net"
|
6
|
+
|
7
|
+
puts "((Create PetriNet [Water]))"
|
8
|
+
net = PetriNet::Net.new(:name => 'Water',
|
9
|
+
:description => 'Creation of water from base elements')
|
10
|
+
net.logger = Logger.new(STDOUT)
|
11
|
+
|
12
|
+
puts "((Create Place 1 [Hydrogen]))"
|
13
|
+
place = PetriNet::Place.new(:name => 'Hydrogen')
|
14
|
+
|
15
|
+
puts "((Add Place 1 [Hydrogen] to PetriNet))"
|
16
|
+
net.add_place(place)
|
17
|
+
|
18
|
+
puts "((Add Place 2 [Oxygen] to PetriNet))"
|
19
|
+
net.add_place(PetriNet::Place.new(:name => 'Oxygen'))
|
20
|
+
|
21
|
+
puts "((Add Place 3 [Water] to PetriNet))"
|
22
|
+
net << PetriNet::Place.new do |p|
|
23
|
+
p.name = 'Water'
|
24
|
+
end
|
25
|
+
|
26
|
+
puts "((Add Transition 1 [Join] to PetriNet))"
|
27
|
+
net.add_transition(PetriNet::Transition.new(:name => 'Join'))
|
28
|
+
|
29
|
+
puts "((Add Arc 1 [Hydrogen.Join] to PetriNet))"
|
30
|
+
net << PetriNet::Arc.new do |a|
|
31
|
+
a.name = 'Hydrogen.Join'
|
32
|
+
a.weight = 2
|
33
|
+
a.add_source(net.objects[net.places['Hydrogen']])
|
34
|
+
a.add_destination(net.objects[net.transitions['Join']])
|
35
|
+
end
|
36
|
+
|
37
|
+
puts "((Add Arc 2 [Oxygen.Join] to PetriNet))"
|
38
|
+
arc = PetriNet::Arc.new do |a|
|
39
|
+
a.name = 'Oxygen.Join'
|
40
|
+
a.add_source(net.objects[net.places['Oxygen']])
|
41
|
+
a.add_destination(net.objects[net.transitions['Join']])
|
42
|
+
end
|
43
|
+
net.add_arc(arc)
|
44
|
+
|
45
|
+
puts "((Add Arc 3 [Join.Water] to PetriNet))"
|
46
|
+
net.add_arc(PetriNet::Arc.new(
|
47
|
+
:name => 'Join.Water',
|
48
|
+
:description => "Join to Water",
|
49
|
+
:source => net.objects[net.transitions["Join"]],
|
50
|
+
:destination => net.objects[net.places["Water"]],
|
51
|
+
:weight => 1
|
52
|
+
)
|
53
|
+
)
|
54
|
+
|
55
|
+
puts
|
56
|
+
puts
|
57
|
+
puts net.inspect
|
58
|
+
puts
|
59
|
+
puts
|
60
|
+
puts net.to_s
|
61
|
+
puts
|
62
|
+
puts
|
63
|
+
puts net.to_gv
|
64
|
+
puts
|
data/test/tc_arc.rb
ADDED
File without changes
|
data/test/tc_edge.rb
ADDED
File without changes
|
data/test/tc_graph.rb
ADDED
File without changes
|
data/test/tc_node.rb
ADDED
File without changes
|
@@ -0,0 +1,320 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'logger'
|
5
|
+
require 'test/unit'
|
6
|
+
require "#{`pwd`.strip}/../lib/petri_net"
|
7
|
+
|
8
|
+
require 'pry'
|
9
|
+
|
10
|
+
class TestPetriNet < Test::Unit::TestCase
|
11
|
+
def setup
|
12
|
+
@net = PetriNet::Net.new(:name => 'Water', :description => 'Creation of water from base elements.')
|
13
|
+
@net.logger = Logger.new(STDOUT)
|
14
|
+
end
|
15
|
+
|
16
|
+
def fill_net
|
17
|
+
@net << PetriNet::Place.new(:name => "testplace")
|
18
|
+
@net << PetriNet::Transition.new(:name => "testtrans")
|
19
|
+
arc = PetriNet::Arc.new do |a|
|
20
|
+
a.name = 'testarc'
|
21
|
+
a.weight = 2
|
22
|
+
a.add_source(@net.get_place 'testplace')
|
23
|
+
a.add_destination(@net.get_transition 'testtrans')
|
24
|
+
end
|
25
|
+
@net << arc
|
26
|
+
end
|
27
|
+
|
28
|
+
def teardown
|
29
|
+
@net.reset
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_create_net
|
33
|
+
net = PetriNet::Net.new(:name => 'Water', :description => 'Creation of water from base elements.')
|
34
|
+
assert_not_nil net
|
35
|
+
assert_equal "Water", net.name, "Name was not properly set"
|
36
|
+
assert_equal "Creation of water from base elements.", net.description, "Description was not properly set"
|
37
|
+
assert_equal 0, net.objects_size, "There should not be any Objects in this fresh and empty net"
|
38
|
+
assert_empty net.arcs, "There should not be any Objects in this fresh and empty net"
|
39
|
+
assert_empty net.transitions, "There should not be any Objects in this fresh and empty net"
|
40
|
+
assert_empty net.places, "There should not be any Objects in this fresh and empty net"
|
41
|
+
assert !net.up_to_date, "There are no cached functions calculated"
|
42
|
+
net.update
|
43
|
+
assert net.up_to_date, "Now we calculated all cached functions without changing anything afterwards, so this schould be up to date"
|
44
|
+
assert_empty net.get_markings, "No Places should mean no markings..."
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_add_place
|
48
|
+
# Create the place
|
49
|
+
place = PetriNet::Place.new(:name => 'Hydrogen')
|
50
|
+
assert_not_nil place
|
51
|
+
assert place.validate
|
52
|
+
|
53
|
+
# Add the place
|
54
|
+
id = @net.add_place(place)
|
55
|
+
assert_equal 1, @net.objects_size
|
56
|
+
assert_equal id, @net.places["Hydrogen"]
|
57
|
+
assert_equal place, @net.get_place("Hydrogen")
|
58
|
+
|
59
|
+
place.add_marking
|
60
|
+
assert_equal 1, place.markings.size
|
61
|
+
place.add_marking
|
62
|
+
assert_equal 2, place.markings.size
|
63
|
+
place.remove_marking
|
64
|
+
assert_equal 1, place.markings.size
|
65
|
+
assert_raise( RuntimeError ){ place.remove_marking(4) }
|
66
|
+
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_add_transition
|
71
|
+
# create the transition
|
72
|
+
transition = PetriNet::Transition.new(:name => 'Join', :description => 'great testing transition')
|
73
|
+
assert_not_nil transition
|
74
|
+
assert transition.validate
|
75
|
+
|
76
|
+
#Add the transition
|
77
|
+
id = @net.add_transition(transition)
|
78
|
+
assert_equal 1, @net.objects_size
|
79
|
+
assert_equal @net.transitions['Join'], id
|
80
|
+
assert_equal @net.get_transition('Join'), transition
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_add_object()
|
84
|
+
assert_equal @net, @net << PetriNet::Place.new(:name => "testplace")
|
85
|
+
assert_equal 1, @net.places.size, "Added only one place, this means there should only be one place"
|
86
|
+
assert_equal 1, @net.objects_size, "Added only one place, this means there should only be one object"
|
87
|
+
@net << PetriNet::Transition.new(:name => "testtrans")
|
88
|
+
assert_equal 1, @net.transitions.size, "Added only one transition, this means there should only be one transition"
|
89
|
+
assert_equal 2, @net.objects_size, "Added one transition to the place, this means there should be exactly two objects"
|
90
|
+
arc = PetriNet::Arc.new do |a|
|
91
|
+
a.name = 'testarc'
|
92
|
+
a.weight = 2
|
93
|
+
a.add_source(@net.get_place 'testplace')
|
94
|
+
a.add_destination(@net.get_transition 'testtrans')
|
95
|
+
end
|
96
|
+
@net << arc
|
97
|
+
assert_equal 1, @net.arcs.size, "Addes only one arc, this means there should only be one arc"
|
98
|
+
assert_equal 3, @net.objects_size, "Added an arc, so there should be exactly three objects now"
|
99
|
+
assert_raise(RuntimeError, "You can't add a Hash, so this should raise an Error"){@net << Hash.new}#
|
100
|
+
array = [PetriNet::Place.new, PetriNet::Transition.new, PetriNet::Transition.new]
|
101
|
+
assert_equal @net, @net << array, "Adding an array should result in the same as adding is one by one"
|
102
|
+
assert_equal 2, @net.places.size, "Adding an array should result in the same as adding is one by one"
|
103
|
+
assert_equal 3, @net.transitions.size, "Adding an array should result in the same as adding is one by one"
|
104
|
+
assert_equal 6, @net.objects_size, "Adding an array should result in the same as adding is one by one"
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_get_place
|
108
|
+
@net << place = PetriNet::Place.new(:name => 'Test')
|
109
|
+
assert_equal place, @net.get_place('Test'), "should be the same as the given place"
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_get_transition
|
113
|
+
@net << transition = PetriNet::Transition.new(:name => 'Test')
|
114
|
+
assert_equal transition, @net.get_transition('Test'), "should be the same transition als the given one"
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_add_arc
|
118
|
+
@net.add_object PetriNet::Transition.new(:name => 'Join', :description => 'great testing transition')
|
119
|
+
@net.add_object PetriNet::Place.new(:name => 'Hydrogen')
|
120
|
+
arc = PetriNet::Arc.new do |a|
|
121
|
+
a.name = 'Hydrogen.Join'
|
122
|
+
a.weight = 2
|
123
|
+
a.add_source(@net.get_place 'Hydrogen')
|
124
|
+
a.add_destination(@net.get_transition 'Join')
|
125
|
+
end
|
126
|
+
assert_not_nil arc
|
127
|
+
assert arc.validate(@net), "the created arc is not valid"
|
128
|
+
|
129
|
+
#add the arc
|
130
|
+
id = @net.add_arc arc
|
131
|
+
assert @net.objects_size > 1
|
132
|
+
assert_equal @net.arcs['Hydrogen.Join'], id
|
133
|
+
assert_equal @net.get_arc('Hydrogen.Join'), arc
|
134
|
+
|
135
|
+
#should not be here :-(
|
136
|
+
transition = @net.get_transition 'Join'
|
137
|
+
assert !transition.activated?, "Transition should not be activated as there are no markings"
|
138
|
+
|
139
|
+
@net.add_object PetriNet::Place.new(:name => 'Oxygen')
|
140
|
+
arc = PetriNet::Arc.new do |a|
|
141
|
+
a.name = 'Join.Oxygen'
|
142
|
+
a.weight = 1
|
143
|
+
a.add_source(@net.get_transition 'Join')
|
144
|
+
a.add_destination(@net.get_place 'Oxygen')
|
145
|
+
end
|
146
|
+
@net << arc
|
147
|
+
@net.get_place('Hydrogen').add_marking(2)
|
148
|
+
assert transition.activated?, "Transition should be activated now"
|
149
|
+
|
150
|
+
#puts @net.generate_reachability_graph.to_gv
|
151
|
+
|
152
|
+
|
153
|
+
#puts
|
154
|
+
# puts @net.get_markings
|
155
|
+
# puts
|
156
|
+
# transition.fire
|
157
|
+
# assert_equal @net.objects[@net.places['Hydrogen']].markings.size, 0, "After firing the transituon, there should be no marking left in this place"
|
158
|
+
#
|
159
|
+
# assert_equal 0, @net.w0(4,3), "There is no arc with this IDs, so there should be 0"
|
160
|
+
# assert_equal 2, @net.w0(@net.places['Hydrogen'], @net.transitions['Join']), "There should be an arc with weight 2"
|
161
|
+
# assert_equal 0, @net.w0(@net.transitions['Join'], @net.places['Hydrogen']), "Wrong direction"
|
162
|
+
#
|
163
|
+
# puts @net.get_markings
|
164
|
+
#puts
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
def test_merge
|
169
|
+
fill_net
|
170
|
+
net2 = PetriNet::Net.new(:name => 'Water2', :description => ' Creation of water from base elements version2.')
|
171
|
+
net2 << PetriNet::Place.new(:name => "testplace2")
|
172
|
+
net2 << PetriNet::Transition.new(:name => "testtrans")
|
173
|
+
arc = PetriNet::Arc.new do |a|
|
174
|
+
a.name = 'testarc'
|
175
|
+
a.weight = 2
|
176
|
+
a.add_source(net2.get_place 'testplace2')
|
177
|
+
a.add_destination(net2.get_transition 'testtrans')
|
178
|
+
end
|
179
|
+
net2 << arc
|
180
|
+
assert_equal "Petri Net [Water]
|
181
|
+
----------------------------
|
182
|
+
Description: Creation of water from base elements.
|
183
|
+
Filename: Water
|
184
|
+
|
185
|
+
Places
|
186
|
+
----------------------------
|
187
|
+
1: testplace (0)
|
188
|
+
4: testplace2 (0)
|
189
|
+
|
190
|
+
Transitions
|
191
|
+
----------------------------
|
192
|
+
2: testtrans
|
193
|
+
|
194
|
+
Arcs
|
195
|
+
----------------------------
|
196
|
+
3: testarc (2) 1 -> 2
|
197
|
+
|
198
|
+
", @net.merge(net2).to_s, "Merge failed, this is only a basic test"
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_generate_reachability_graph
|
202
|
+
assert_equal "Reachability Graph [Water]
|
203
|
+
----------------------------
|
204
|
+
Description:
|
205
|
+
Filename:
|
206
|
+
|
207
|
+
Nodes
|
208
|
+
----------------------------
|
209
|
+
1: Node1 ([])
|
210
|
+
|
211
|
+
Edges
|
212
|
+
----------------------------
|
213
|
+
|
214
|
+
", @net.generate_reachability_graph().to_s, "Simple Reachability Graph with only one reachable state"
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_w0
|
218
|
+
fill_net
|
219
|
+
assert_equal 2, @net.w0(1,2), "The weight of the arc between 1 aud 2 is 2"
|
220
|
+
assert_equal 0, @net.w0(2,1), "The other direction should be 0 because arcs are directed"
|
221
|
+
assert_equal 0, @net.w0(3,6), "If there is no arc, there should not be a weight, so 0"
|
222
|
+
end
|
223
|
+
|
224
|
+
def test_update
|
225
|
+
fill_net
|
226
|
+
assert !@net.up_to_date, "At first the net should be not up to date"
|
227
|
+
@net.update
|
228
|
+
assert @net.up_to_date, "Afterwards the net should be up to date and all cached functions should be calculated"
|
229
|
+
end
|
230
|
+
|
231
|
+
def test_generate_weight_function
|
232
|
+
fill_net
|
233
|
+
weight = {[1,2] => 2}
|
234
|
+
assert_equal weight, @net.generate_weight_function
|
235
|
+
end
|
236
|
+
|
237
|
+
def test_get_markings
|
238
|
+
fill_net
|
239
|
+
@net << PetriNet::Place.new(name: 'place2')
|
240
|
+
@net.get_place('testplace').add_marking 2
|
241
|
+
@net.get_place('place2').add_marking 3
|
242
|
+
|
243
|
+
assert_equal [2,3], @net.get_markings
|
244
|
+
end
|
245
|
+
|
246
|
+
def test_set_markings
|
247
|
+
fill_net
|
248
|
+
@net << PetriNet::Place.new(name: 'place2')
|
249
|
+
@net.set_markings [2,3]
|
250
|
+
assert_equal [2,3], @net.get_markings
|
251
|
+
end
|
252
|
+
|
253
|
+
def test_objects_size
|
254
|
+
fill_net
|
255
|
+
assert_equal 3, @net.objects_size
|
256
|
+
end
|
257
|
+
|
258
|
+
|
259
|
+
# def test_create_marking
|
260
|
+
# place = PetriNet::Place.new(:name => 'Hydrogen')
|
261
|
+
# marking = PetriNet::Marking.new
|
262
|
+
# place.add_marking
|
263
|
+
# assert place.markings.length > 0
|
264
|
+
# end
|
265
|
+
|
266
|
+
end
|
267
|
+
COMMENTED_OUT = <<-EOC
|
268
|
+
puts "((Create Place 1 [Hydrogen]))"
|
269
|
+
place = PetriNet::Place.new(:name => 'Hydrogen')
|
270
|
+
|
271
|
+
puts "((Add Place 1 [Hydrogen] to PetriNet))"
|
272
|
+
net.add_place(place)
|
273
|
+
|
274
|
+
puts "((Add Place 2 [Oxygen] to PetriNet))"
|
275
|
+
net.add_place(PetriNet::Place.new(:name => 'Oxygen'))
|
276
|
+
|
277
|
+
puts "((Add Place 3 [Water] to PetriNet))"
|
278
|
+
net << PetriNet::Place.new do |p|
|
279
|
+
p.name = 'Water'
|
280
|
+
end
|
281
|
+
|
282
|
+
puts "((Add Transition 1 [Join] to PetriNet))"
|
283
|
+
net.add_transition(PetriNet::Transition.new(:name => 'Join'))
|
284
|
+
|
285
|
+
puts "((Add Arc 1 [Hydrogen.Join] to PetriNet))"
|
286
|
+
net << PetriNet::Arc.new do |a|
|
287
|
+
a.name = 'Hydrogen.Join'
|
288
|
+
a.weight = 2
|
289
|
+
a.add_source(net.objects[net.places['Hydrogen']])
|
290
|
+
a.add_destination(net.objects[net.transitions['Join']])
|
291
|
+
end
|
292
|
+
|
293
|
+
puts "((Add Arc 2 [Oxygen.Join] to PetriNet))"
|
294
|
+
arc = PetriNet::Arc.new do |a|
|
295
|
+
a.name = 'Oxygen.Join'
|
296
|
+
a.add_source(net.objects[net.places['Oxygen']])
|
297
|
+
a.add_destination(net.objects[net.transitions['Join']])
|
298
|
+
end
|
299
|
+
net.add_arc(arc)
|
300
|
+
|
301
|
+
puts "((Add Arc 3 [Join.Water] to PetriNet))"
|
302
|
+
net.add_arc(PetriNet::Arc.new(
|
303
|
+
:name => 'Join.Water',
|
304
|
+
:description => "Join to Water",
|
305
|
+
:source => net.objects[net.transitions["Join"]],
|
306
|
+
:destination => net.objects[net.places["Water"]],
|
307
|
+
:weight => 1
|
308
|
+
)
|
309
|
+
)
|
310
|
+
|
311
|
+
puts
|
312
|
+
puts
|
313
|
+
puts net.inspect
|
314
|
+
puts
|
315
|
+
puts
|
316
|
+
puts net.to_s
|
317
|
+
puts
|
318
|
+
puts
|
319
|
+
EOC
|
320
|
+
|
data/test/tc_place.rb
ADDED
File without changes
|
data/test/ts_test_all.rb
ADDED
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: petri_net
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- cclausen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-12-26 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A Petri net modeling gem
|
14
|
+
email:
|
15
|
+
- '"cclausen@tzi.de"'
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- .ruby-version
|
21
|
+
- CHANGELOG
|
22
|
+
- LICENSE
|
23
|
+
- README.rdoc
|
24
|
+
- Rakefile
|
25
|
+
- lib/petri_net.rb
|
26
|
+
- lib/petri_net/arc.rb
|
27
|
+
- lib/petri_net/base.rb
|
28
|
+
- lib/petri_net/edge.rb
|
29
|
+
- lib/petri_net/marking.rb
|
30
|
+
- lib/petri_net/net.rb
|
31
|
+
- lib/petri_net/node.rb
|
32
|
+
- lib/petri_net/place.rb
|
33
|
+
- lib/petri_net/reachability_graph.rb
|
34
|
+
- lib/petri_net/transition.rb
|
35
|
+
- test/create.rb
|
36
|
+
- test/tc_arc.rb
|
37
|
+
- test/tc_edge.rb
|
38
|
+
- test/tc_graph.rb
|
39
|
+
- test/tc_node.rb
|
40
|
+
- test/tc_petri_net.rb
|
41
|
+
- test/tc_place.rb
|
42
|
+
- test/tc_transition.rb
|
43
|
+
- test/ts_test_all.rb
|
44
|
+
homepage: https://github.com/cclausen/petri
|
45
|
+
licenses:
|
46
|
+
- MIT
|
47
|
+
metadata: {}
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options: []
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
requirements: []
|
63
|
+
rubyforge_project:
|
64
|
+
rubygems_version: 2.0.3
|
65
|
+
signing_key:
|
66
|
+
specification_version: 4
|
67
|
+
summary: You can create Petri Nets and do some calculations with them like generating
|
68
|
+
the Reachability Graph
|
69
|
+
test_files:
|
70
|
+
- test/create.rb
|
71
|
+
- test/tc_arc.rb
|
72
|
+
- test/tc_edge.rb
|
73
|
+
- test/tc_graph.rb
|
74
|
+
- test/tc_node.rb
|
75
|
+
- test/tc_petri_net.rb
|
76
|
+
- test/tc_place.rb
|
77
|
+
- test/tc_transition.rb
|
78
|
+
- test/ts_test_all.rb
|