tb 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/README +156 -5
  2. data/bin/tb +2 -1110
  3. data/lib/tb.rb +4 -2
  4. data/lib/tb/catreader.rb +131 -0
  5. data/lib/tb/cmd_cat.rb +65 -0
  6. data/lib/tb/cmd_consecutive.rb +79 -0
  7. data/lib/tb/cmd_crop.rb +105 -0
  8. data/lib/tb/cmd_cross.rb +119 -0
  9. data/lib/tb/cmd_csv.rb +42 -0
  10. data/lib/tb/cmd_cut.rb +77 -0
  11. data/lib/tb/cmd_grep.rb +76 -0
  12. data/lib/tb/cmd_group.rb +82 -0
  13. data/lib/tb/cmd_gsub.rb +77 -0
  14. data/lib/tb/cmd_help.rb +98 -0
  15. data/lib/tb/cmd_join.rb +81 -0
  16. data/lib/tb/cmd_json.rb +60 -0
  17. data/lib/tb/cmd_ls.rb +273 -0
  18. data/lib/tb/cmd_mheader.rb +77 -0
  19. data/lib/tb/cmd_newfield.rb +59 -0
  20. data/lib/tb/cmd_pnm.rb +43 -0
  21. data/lib/tb/cmd_pp.rb +70 -0
  22. data/lib/tb/cmd_rename.rb +58 -0
  23. data/lib/tb/cmd_shape.rb +67 -0
  24. data/lib/tb/cmd_sort.rb +58 -0
  25. data/lib/tb/cmd_svn_log.rb +158 -0
  26. data/lib/tb/cmd_tsv.rb +43 -0
  27. data/lib/tb/cmd_yaml.rb +47 -0
  28. data/lib/tb/cmdmain.rb +45 -0
  29. data/lib/tb/cmdtop.rb +58 -0
  30. data/lib/tb/cmdutil.rb +327 -0
  31. data/lib/tb/csv.rb +30 -6
  32. data/lib/tb/fieldset.rb +39 -41
  33. data/lib/tb/pager.rb +132 -0
  34. data/lib/tb/pnm.rb +357 -0
  35. data/lib/tb/reader.rb +18 -128
  36. data/lib/tb/record.rb +3 -3
  37. data/lib/tb/ropen.rb +70 -0
  38. data/lib/tb/{pathfinder.rb → search.rb} +69 -34
  39. data/lib/tb/tsv.rb +29 -1
  40. data/sample/colors.ppm +0 -0
  41. data/sample/gradation.pgm +0 -0
  42. data/sample/langs.csv +46 -0
  43. data/sample/tbplot +293 -0
  44. data/test-all-cov.rb +65 -0
  45. data/test-all.rb +5 -0
  46. data/test/test_basic.rb +99 -2
  47. data/test/test_catreader.rb +27 -0
  48. data/test/test_cmd_cat.rb +118 -0
  49. data/test/test_cmd_consecutive.rb +90 -0
  50. data/test/test_cmd_crop.rb +101 -0
  51. data/test/test_cmd_cross.rb +113 -0
  52. data/test/test_cmd_csv.rb +129 -0
  53. data/test/test_cmd_cut.rb +100 -0
  54. data/test/test_cmd_grep.rb +89 -0
  55. data/test/test_cmd_group.rb +181 -0
  56. data/test/test_cmd_gsub.rb +103 -0
  57. data/test/test_cmd_help.rb +190 -0
  58. data/test/test_cmd_join.rb +197 -0
  59. data/test/test_cmd_json.rb +75 -0
  60. data/test/test_cmd_ls.rb +203 -0
  61. data/test/test_cmd_mheader.rb +86 -0
  62. data/test/test_cmd_newfield.rb +63 -0
  63. data/test/test_cmd_pnm.rb +35 -0
  64. data/test/test_cmd_pp.rb +62 -0
  65. data/test/test_cmd_rename.rb +91 -0
  66. data/test/test_cmd_shape.rb +50 -0
  67. data/test/test_cmd_sort.rb +105 -0
  68. data/test/test_cmd_tsv.rb +67 -0
  69. data/test/test_cmd_yaml.rb +55 -0
  70. data/test/test_cmdtty.rb +154 -0
  71. data/test/test_cmdutil.rb +43 -0
  72. data/test/test_csv.rb +10 -0
  73. data/test/test_fieldset.rb +42 -0
  74. data/test/test_pager.rb +142 -0
  75. data/test/test_pnm.rb +374 -0
  76. data/test/test_reader.rb +147 -0
  77. data/test/test_record.rb +49 -0
  78. data/test/test_search.rb +575 -0
  79. data/test/test_tsv.rb +7 -0
  80. metadata +108 -5
  81. data/lib/tb/qtsv.rb +0 -93
@@ -0,0 +1,147 @@
1
+ require 'tb'
2
+ require 'test/unit'
3
+ require 'tmpdir'
4
+
5
+ class TestTbReader < Test::Unit::TestCase
6
+ def test_load_csv
7
+ Dir.mktmpdir {|d|
8
+ open(i="#{d}/i.csv", "w") {|f| f << <<-"End".gsub(/^[ \t]+/, '') }
9
+ a,b
10
+ 1,3
11
+ 2,4
12
+ End
13
+ t = Tb.load_csv(i)
14
+ records = []
15
+ t.each_record {|record| records << record.to_h }
16
+ assert_equal(
17
+ [{"a"=>"1", "b"=>"3"},
18
+ {"a"=>"2", "b"=>"4"}],
19
+ records)
20
+ }
21
+ end
22
+
23
+ def test_load_tsv
24
+ Dir.mktmpdir {|d|
25
+ open(i="#{d}/i.tsv", "w") {|f| f << <<-"End".gsub(/^[ \t]+/, '') }
26
+ a\tb
27
+ 1\t3
28
+ 2\t4
29
+ End
30
+ t = Tb.load_tsv(i)
31
+ records = []
32
+ t.each_record {|record| records << record.to_h }
33
+ assert_equal(
34
+ [{"a"=>"1", "b"=>"3"},
35
+ {"a"=>"2", "b"=>"4"}],
36
+ records)
37
+ }
38
+ end
39
+
40
+ def test_parse_csv
41
+ csv = <<-'End'.gsub(/^[ \t]+/, '')
42
+ 1,2
43
+ 3,4
44
+ End
45
+ t = Tb.parse_csv(csv, 'a', 'b')
46
+ records = []
47
+ t.each_record {|record|
48
+ records << record.to_h
49
+ }
50
+ assert_equal(
51
+ [{"a"=>"1", "b"=>"2"},
52
+ {"a"=>"3", "b"=>"4"}],
53
+ records)
54
+ end
55
+
56
+ def test_parse_tsv
57
+ csv = <<-"End".gsub(/^[ \t]+/, '')
58
+ 1\t2
59
+ 3\t4
60
+ End
61
+ t = Tb.parse_tsv(csv, 'a', 'b')
62
+ records = []
63
+ t.each_record {|record|
64
+ records << record.to_h
65
+ }
66
+ assert_equal(
67
+ [{"a"=>"1", "b"=>"2"},
68
+ {"a"=>"3", "b"=>"4"}],
69
+ records)
70
+ end
71
+
72
+ def test_open
73
+ Dir.mktmpdir {|d|
74
+ open(ic="#{d}/c", "w") {|f| f << <<-"End".gsub(/^[ \t]+/, '') }
75
+ a,b
76
+ 1,3
77
+ End
78
+ open(it="#{d}/t", "w") {|f| f << <<-"End".gsub(/^[ \t]+/, '') }
79
+ a\tb
80
+ 1\t3
81
+ End
82
+ Tb::Reader.open("csv:#{ic}") {|r|
83
+ assert_equal(%w[a b], r.header)
84
+ assert_equal([%w[1 3]], r.read_all)
85
+ }
86
+ Tb::Reader.open("tsv:#{it}") {|r|
87
+ assert_equal(%w[a b], r.header)
88
+ assert_equal([%w[1 3]], r.read_all)
89
+ }
90
+ Tb::Reader.open(ic) {|r|
91
+ assert_equal(%w[a b], r.header)
92
+ assert_equal([%w[1 3]], r.read_all)
93
+ }
94
+ assert_raise(ArgumentError) { Tb::Reader.open(Object.new) }
95
+ }
96
+ end
97
+
98
+ def test_field_index
99
+ Dir.mktmpdir {|d|
100
+ open(i="#{d}/i.csv", "w") {|f| f << <<-"End".gsub(/^[ \t]+/, '') }
101
+ a,b
102
+ 1,3
103
+ End
104
+ Tb::Reader.open(i) {|r|
105
+ assert_equal(%w[a b], r.header)
106
+ assert_equal([%w[1 3]], r.read_all)
107
+ assert_equal("a", r.field_from_index(0))
108
+ assert_equal("b", r.field_from_index(1))
109
+ assert_raise(ArgumentError) { r.field_from_index(2) }
110
+ assert_equal(0, r.index_from_field("a"))
111
+ assert_equal(1, r.index_from_field("b"))
112
+ assert_raise(ArgumentError) { r.index_from_field("c") }
113
+ assert_raise(ArgumentError) { r.index_from_field("2") }
114
+ assert_equal("1", r.field_from_index_ex(2))
115
+ assert_equal(3, r.index_from_field_ex("2"))
116
+ }
117
+ }
118
+ end
119
+
120
+ def test_header_ignore_empty
121
+ csv = "\n" + <<-'End'.gsub(/^[ \t]+/, '')
122
+ a,b
123
+ 1,2
124
+ 3,4
125
+ End
126
+ t = Tb.parse_csv(csv)
127
+ records = []
128
+ t.each_record {|record|
129
+ records << record.to_h
130
+ }
131
+ assert_equal(
132
+ [{"a"=>"1", "b"=>"2"},
133
+ {"a"=>"3", "b"=>"4"}],
134
+ records)
135
+ end
136
+
137
+ def test_header_empty_only
138
+ csv = "\n"
139
+ t = Tb.parse_csv(csv)
140
+ records = []
141
+ t.each_record {|record|
142
+ records << record.to_h
143
+ }
144
+ assert_equal([], records)
145
+ end
146
+
147
+ end
@@ -2,6 +2,54 @@ require 'tb'
2
2
  require 'test/unit'
3
3
 
4
4
  class TestTbRecord < Test::Unit::TestCase
5
+ def test_pretty_print
6
+ t = Tb.new %w[fruit color],
7
+ %w[apple red],
8
+ %w[banana yellow],
9
+ %w[orange orange]
10
+ s = t.get_record(0).pretty_inspect
11
+ assert_match(/apple/, s)
12
+ assert_match(/red/, s)
13
+ end
14
+
15
+ def test_has_field?
16
+ t = Tb.new %w[fruit color],
17
+ %w[apple red],
18
+ %w[banana yellow],
19
+ %w[orange orange]
20
+ r = t.get_record(0)
21
+ assert_equal(true, r.has_field?("fruit"))
22
+ assert_equal(false, r.has_field?("price"))
23
+ end
24
+
25
+ def test_to_a
26
+ t = Tb.new %w[fruit color],
27
+ %w[apple red],
28
+ %w[banana yellow],
29
+ %w[orange orange]
30
+ assert_equal([["fruit", "apple"], ["color", "red"]], t.get_record(0).to_a)
31
+ end
32
+
33
+ def test_to_a_with_reserved
34
+ t = Tb.new %w[fruit color],
35
+ %w[apple red],
36
+ %w[banana yellow],
37
+ %w[orange orange]
38
+ assert_equal([["_recordid", 0], ["fruit", "apple"], ["color", "red"]], t.get_record(0).to_a_with_reserved)
39
+ end
40
+
41
+ def test_each_with_reserved
42
+ t = Tb.new %w[fruit color],
43
+ %w[apple red],
44
+ %w[banana yellow],
45
+ %w[orange orange]
46
+ result = []
47
+ t.get_record(0).each_with_reserved {|r|
48
+ result << r
49
+ }
50
+ assert_equal([["_recordid", 0], ["fruit", "apple"], ["color", "red"]], result)
51
+ end
52
+
5
53
  def test_values_at
6
54
  t = Tb.new %w[fruit color],
7
55
  %w[apple red],
@@ -9,4 +57,5 @@ class TestTbRecord < Test::Unit::TestCase
9
57
  %w[orange orange]
10
58
  assert_equal(["apple", "red"], t.get_record(0).values_at("fruit", "color"))
11
59
  end
60
+
12
61
  end
@@ -0,0 +1,575 @@
1
+ require 'tb'
2
+ require 'test/unit'
3
+
4
+ class TestTbPathFinder < Test::Unit::TestCase
5
+ def test_strary_to_aa
6
+ assert_equal([["a", "b"], ["c", "d"]],
7
+ Tb::Search.strary_to_aa(["ab", "cd"]))
8
+ end
9
+
10
+ def test_match
11
+ ret = Tb::Search.match(
12
+ "b",
13
+ [%w[a b],
14
+ %w[c d]])
15
+ spos, epos, _ = ret
16
+ assert_equal([1, 0], spos)
17
+ assert_equal([1, 0], epos)
18
+ end
19
+
20
+ def test_each_match_with_spos
21
+ res = []
22
+ Tb::Search.each_match(
23
+ "b",
24
+ [%w[a b],
25
+ %w[c d]],
26
+ [1,0]) {|spos, epos, cap|
27
+ res << [spos, epos, cap]
28
+ }
29
+ assert_equal(1, res.size)
30
+ spos, epos, _ = res[0]
31
+ assert_equal([1, 0], spos)
32
+ assert_equal([1, 0], epos)
33
+ end
34
+
35
+ def test_each_match_without_spos
36
+ res = []
37
+ Tb::Search.each_match(
38
+ "b",
39
+ [%w[a b],
40
+ %w[c d]]) {|spos, epos, cap|
41
+ res << [spos, epos, cap]
42
+ }
43
+ assert_equal(1, res.size)
44
+ spos, epos, _ = res[0]
45
+ assert_equal([1, 0], spos)
46
+ assert_equal([1, 0], epos)
47
+ end
48
+
49
+ def test_pat_nil
50
+ res = []
51
+ Tb::Search.each_match(
52
+ nil,
53
+ [%w[a b],
54
+ %w[c d]],
55
+ [1,0]) {|spos, epos, cap|
56
+ res << [spos, epos, cap]
57
+ }
58
+ assert_equal(1, res.size)
59
+ spos, epos, _ = res[0]
60
+ assert_equal([1, 0], spos)
61
+ assert_equal([1, 0], epos)
62
+ end
63
+
64
+ def test_pat_regexp1
65
+ res = []
66
+ Tb::Search.each_match(
67
+ /[bc]/,
68
+ [%w[a b],
69
+ %w[c d]]) {|spos, epos, cap|
70
+ res << [spos, epos, cap]
71
+ }
72
+ assert_equal(2, res.size)
73
+ assert_equal([[1,0], [1,0]], res[0][0..1])
74
+ assert_equal([[0,1], [0,1]], res[1][0..1])
75
+ end
76
+
77
+ def test_pat_regexp2
78
+ res = []
79
+ Tb::Search.each_match(
80
+ [:regexp, /[bc]/],
81
+ [%w[a b],
82
+ %w[c d]]) {|spos, epos, cap|
83
+ res << [spos, epos, cap]
84
+ }
85
+ assert_equal(2, res.size)
86
+ assert_equal([[1,0], [1,0]], res[0][0..1])
87
+ assert_equal([[0,1], [0,1]], res[1][0..1])
88
+ end
89
+
90
+ def test_pat_alt
91
+ res = []
92
+ Tb::Search.each_match(
93
+ [:alt, "b", "c"],
94
+ [%w[a b],
95
+ %w[c d]]) {|spos, epos, cap|
96
+ res << [spos, epos, cap]
97
+ }
98
+ assert_equal(2, res.size)
99
+ assert_equal([[1,0], [1,0]], res[0][0..1])
100
+ assert_equal([[0,1], [0,1]], res[1][0..1])
101
+ end
102
+
103
+ def test_pat_lit
104
+ res = []
105
+ Tb::Search.each_match(
106
+ [:lit, "b"],
107
+ [%w[a b],
108
+ %w[c d]]) {|spos, epos, cap|
109
+ res << [spos, epos, cap]
110
+ }
111
+ assert_equal(1, res.size)
112
+ assert_equal([[1,0], [1,0]], res[0][0..1])
113
+ end
114
+
115
+ def test_pat_nsew
116
+ res = []
117
+ Tb::Search.each_match(
118
+ [:cat, "b", :s, "d", :w, "c", :n, "a", :e, "b"],
119
+ [%w[a b],
120
+ %w[c d]]) {|spos, epos, cap|
121
+ res << [spos, epos, cap]
122
+ }
123
+ assert_equal(1, res.size)
124
+ assert_equal([[1,0], [1,0]], res[0][0..1])
125
+ end
126
+
127
+ def test_pat_direction8
128
+ res = []
129
+ Tb::Search.each_match(
130
+ [:cat, "b", :se, "f", :sw, "h", :nw, "d", :ne, "b"],
131
+ [%w[a b c],
132
+ %w[d e f],
133
+ %w[g h i]]) {|spos, epos, cap|
134
+ res << [spos, epos, cap]
135
+ }
136
+ assert_equal(1, res.size)
137
+ assert_equal([[1,0], [1,0]], res[0][0..1])
138
+ end
139
+
140
+ def test_pat_rmove
141
+ res = []
142
+ Tb::Search.each_match(
143
+ [:cat, "b",
144
+ [:rmove, 0, 1], "d",
145
+ [:rmove, -1, 0], "c",
146
+ [:rmove, 0, -1], "a",
147
+ [:rmove, 1, 0], "b"],
148
+ [%w[a b],
149
+ %w[c d]]) {|spos, epos, cap|
150
+ res << [spos, epos, cap]
151
+ }
152
+ assert_equal(1, res.size)
153
+ assert_equal([[1,0], [1,0]], res[0][0..1])
154
+ end
155
+
156
+ def test_pat_rep
157
+ res = []
158
+ Tb::Search.each_match(
159
+ [:cat, "a", :e, [:rep, "b", :e]],
160
+ [%w[a b b d],
161
+ %w[c d c d]]) {|spos, epos, cap|
162
+ res << [spos, epos, cap]
163
+ }
164
+ assert_equal(3, res.size)
165
+ assert_equal([[0,0], [3,0]], res[0][0..1])
166
+ assert_equal([[0,0], [2,0]], res[1][0..1])
167
+ assert_equal([[0,0], [1,0]], res[2][0..1])
168
+ end
169
+
170
+ def test_pat_rep_to_boundary
171
+ res = []
172
+ Tb::Search.each_match(
173
+ [:rep, "a", :e],
174
+ [%w[a a]],
175
+ [0,0]) {|spos, epos, cap|
176
+ res << [spos, epos, cap]
177
+ }
178
+ assert_equal(3, res.size)
179
+ assert_equal([[0,0], [2,0]], res[0][0..1])
180
+ assert_equal([[0,0], [1,0]], res[1][0..1])
181
+ assert_equal([[0,0], [0,0]], res[2][0..1])
182
+ end
183
+
184
+ def test_pat_rep1
185
+ res = []
186
+ Tb::Search.each_match(
187
+ [:cat, "a", :e, [:rep1, "b", :e]],
188
+ [%w[a b b d],
189
+ %w[c d c d]]) {|spos, epos, cap|
190
+ res << [spos, epos, cap]
191
+ }
192
+ assert_equal(2, res.size)
193
+ assert_equal([[0,0], [3,0]], res[0][0..1])
194
+ assert_equal([[0,0], [2,0]], res[1][0..1])
195
+ end
196
+
197
+ def test_pat_rep_nongreedy
198
+ res = []
199
+ Tb::Search.each_match(
200
+ [:cat, "a", :e, [:rep_nongreedy, "b", :e]],
201
+ [%w[a b b d],
202
+ %w[c d c d]]) {|spos, epos, cap|
203
+ res << [spos, epos, cap]
204
+ }
205
+ assert_equal(3, res.size)
206
+ assert_equal([[0,0], [1,0]], res[0][0..1])
207
+ assert_equal([[0,0], [2,0]], res[1][0..1])
208
+ assert_equal([[0,0], [3,0]], res[2][0..1])
209
+ end
210
+
211
+ def test_pat_rep1_nongreedy
212
+ res = []
213
+ Tb::Search.each_match(
214
+ [:cat, "a", :e, [:rep1_nongreedy, "b", :e]],
215
+ [%w[a b b d],
216
+ %w[c d c d]]) {|spos, epos, cap|
217
+ res << [spos, epos, cap]
218
+ }
219
+ assert_equal(2, res.size)
220
+ assert_equal([[0,0], [2,0]], res[0][0..1])
221
+ assert_equal([[0,0], [3,0]], res[1][0..1])
222
+ end
223
+
224
+ def test_pat_opt
225
+ res = []
226
+ Tb::Search.each_match(
227
+ [:cat, "a", :e, [:opt, "b", :e]],
228
+ [%w[a b b d],
229
+ %w[c d c d]]) {|spos, epos, cap|
230
+ res << [spos, epos, cap]
231
+ }
232
+ assert_equal(2, res.size)
233
+ assert_equal([[0,0], [2,0]], res[0][0..1])
234
+ assert_equal([[0,0], [1,0]], res[1][0..1])
235
+ end
236
+
237
+ def test_pat_opt_nongreedy
238
+ res = []
239
+ Tb::Search.each_match(
240
+ [:cat, "a", :e, [:opt_nongreedy, "b", :e]],
241
+ [%w[a b b d],
242
+ %w[c d c d]]) {|spos, epos, cap|
243
+ res << [spos, epos, cap]
244
+ }
245
+ assert_equal(2, res.size)
246
+ assert_equal([[0,0], [1,0]], res[0][0..1])
247
+ assert_equal([[0,0], [2,0]], res[1][0..1])
248
+ end
249
+
250
+ def test_pat_repn
251
+ res = []
252
+ Tb::Search.each_match(
253
+ [:cat, "a", :e, [:repn, 2, "b", :e]],
254
+ [%w[a b b b d],
255
+ %w[c d c d x]]) {|spos, epos, cap|
256
+ res << [spos, epos, cap]
257
+ }
258
+ assert_equal(1, res.size)
259
+ assert_equal([[0,0], [3,0]], res[0][0..1])
260
+ end
261
+
262
+ def test_pat_repeat
263
+ res = []
264
+ Tb::Search.each_match(
265
+ [:cat, "a", :e, [:repeat, :v, 1, 2, "b", :e]],
266
+ [%w[a b b b d],
267
+ %w[c d c d x]]) {|spos, epos, cap|
268
+ res << [spos, epos, cap]
269
+ }
270
+ assert_equal(2, res.size)
271
+ assert_equal([[0,0], [3,0]], res[0][0..1])
272
+ assert_equal(2, res[0][2][:v])
273
+ assert_equal([[0,0], [2,0]], res[1][0..1])
274
+ assert_equal(1, res[1][2][:v])
275
+ end
276
+
277
+ def test_pat_repeat_empty
278
+ res = []
279
+ Tb::Search.each_match(
280
+ [:rep, [:rep, "a", :e]],
281
+ [%w[a a b]],
282
+ [0,0]) {|spos, epos, cap|
283
+ res << [spos, epos, cap]
284
+ }
285
+ assert_equal(4, res.size)
286
+ assert_equal([[0,0], [2,0]], res[0][0..1])
287
+ assert_equal([[0,0], [2,0]], res[1][0..1])
288
+ assert_equal([[0,0], [1,0]], res[2][0..1])
289
+ assert_equal([[0,0], [0,0]], res[3][0..1])
290
+ end
291
+
292
+ def test_pat_bfs
293
+ res = []
294
+ Tb::Search.each_match(
295
+ [:bfs, [:pos], [:cat, [:alt, :e, :s], "a"]],
296
+ [%w[a a a a a],
297
+ %w[a b b b b],
298
+ %w[a b b b b]],
299
+ [0,0]) {|spos, epos, cap|
300
+ res << [spos, epos, cap]
301
+ }
302
+ assert_equal(7, res.size)
303
+ assert_equal([[0, 0], [0, 0], Tb::Search::EmptyState], res[0])
304
+ assert_equal([[0, 0], [1, 0], Tb::Search::EmptyState], res[1])
305
+ assert_equal([[0, 0], [0, 1], Tb::Search::EmptyState], res[2])
306
+ assert_equal([[0, 0], [2, 0], Tb::Search::EmptyState], res[3])
307
+ assert_equal([[0, 0], [0, 2], Tb::Search::EmptyState], res[4])
308
+ assert_equal([[0, 0], [3, 0], Tb::Search::EmptyState], res[5])
309
+ assert_equal([[0, 0], [4, 0], Tb::Search::EmptyState], res[6])
310
+ end
311
+
312
+ def test_pat_grid_start_goal
313
+ res = []
314
+ Tb::Search.each_match(
315
+ [:grid,
316
+ [:start, "b", "a"],
317
+ ["b", "a", "b"],
318
+ ["a", "b", :goal]],
319
+ [%w[a b a b a],
320
+ %w[b a b a b],
321
+ %w[a b a b a]]) {|spos, epos, cap|
322
+ res << [spos, epos, cap]
323
+ }
324
+ assert_equal(2, res.size)
325
+ assert_equal([[0, 0], [2, 2], Tb::Search::EmptyState], res[0])
326
+ assert_equal([[2, 0], [4, 2], Tb::Search::EmptyState], res[1])
327
+ end
328
+
329
+ def test_pat_grid_start_goal_with_pattern
330
+ res = []
331
+ Tb::Search.each_match(
332
+ [:grid,
333
+ [[:start, "a"], "b", "a"],
334
+ ["b", "a", "b"],
335
+ ["a", "b", [:goal, "a"]]],
336
+ [%w[a b a b a],
337
+ %w[b a b a b],
338
+ %w[a b a b a]]) {|spos, epos, cap|
339
+ res << [spos, epos, cap]
340
+ }
341
+ assert_equal(2, res.size)
342
+ assert_equal([[0, 0], [2, 2], Tb::Search::EmptyState], res[0])
343
+ assert_equal([[2, 0], [4, 2], Tb::Search::EmptyState], res[1])
344
+ end
345
+
346
+ def test_pat_grid_origin
347
+ res = []
348
+ Tb::Search.each_match(
349
+ [:grid,
350
+ ["a", "b", "a"],
351
+ ["b", :origin, "b"],
352
+ ["a", "b", "a"]],
353
+ [%w[a b a b a],
354
+ %w[b a b a b],
355
+ %w[a b a b a]]) {|spos, epos, cap|
356
+ res << [spos, epos, cap]
357
+ }
358
+ assert_equal(2, res.size)
359
+ assert_equal([[1, 1], [1, 1], Tb::Search::EmptyState], res[0])
360
+ assert_equal([[3, 1], [3, 1], Tb::Search::EmptyState], res[1])
361
+ end
362
+
363
+ def test_pat_grid_origin_with_pattern
364
+ res = []
365
+ Tb::Search.each_match(
366
+ [:grid,
367
+ ["a", "b", "a"],
368
+ ["b", [:origin, "a"], "b"],
369
+ ["a", "b", "a"]],
370
+ [%w[a b a b a],
371
+ %w[b a b a b],
372
+ %w[a b a b a]]) {|spos, epos, cap|
373
+ res << [spos, epos, cap]
374
+ }
375
+ assert_equal(2, res.size)
376
+ assert_equal([[1, 1], [1, 1], Tb::Search::EmptyState], res[0])
377
+ assert_equal([[3, 1], [3, 1], Tb::Search::EmptyState], res[1])
378
+ end
379
+
380
+ def test_pat_capval
381
+ res = []
382
+ Tb::Search.each_match(
383
+ [:capval, :name],
384
+ [%w[a b]]) {|spos, epos, cap|
385
+ res << [spos, epos, cap]
386
+ }
387
+ assert_equal(2, res.size)
388
+ assert_equal([[0, 0], [0, 0], Tb::Search::State.make(:name => "a")], res[0])
389
+ assert_equal([[1, 0], [1, 0], Tb::Search::State.make(:name => "b")], res[1])
390
+ end
391
+
392
+ def test_pat_capval_outside
393
+ res = []
394
+ Tb::Search.each_match(
395
+ [:cat, :n, [:capval, :name]],
396
+ [%w[a b]],
397
+ [0,0]) {|spos, epos, cap|
398
+ res << [spos, epos, cap]
399
+ }
400
+ assert_equal(1, res.size)
401
+ assert_equal([[0, 0], [0, -1], Tb::Search::State.make(:name => nil)], res[0])
402
+ end
403
+
404
+ def test_pat_refval
405
+ res = []
406
+ Tb::Search.each_match(
407
+ [:cat, [:capval, :name], [:rep1, :e, [:refval, :name]]],
408
+ [%w[a a b b b c]]) {|spos, epos, cap|
409
+ res << [spos, epos, cap]
410
+ }
411
+ assert_equal(4, res.size)
412
+ assert_equal([[0, 0], [1, 0], Tb::Search::State.make(:name => "a")], res[0])
413
+ assert_equal([[2, 0], [4, 0], Tb::Search::State.make(:name => "b")], res[1])
414
+ assert_equal([[2, 0], [3, 0], Tb::Search::State.make(:name => "b")], res[2])
415
+ assert_equal([[3, 0], [4, 0], Tb::Search::State.make(:name => "b")], res[3])
416
+ end
417
+
418
+ def test_pat_tmp_pos
419
+ res = []
420
+ Tb::Search.each_match(
421
+ [:cat, "a", [:tmp_pos, 1, 0, "b"]],
422
+ [%w[a b a a b b]]) {|spos, epos, cap|
423
+ res << [spos, epos, cap]
424
+ }
425
+ assert_equal(2, res.size)
426
+ assert_equal([[0, 0], [0, 0], Tb::Search::EmptyState], res[0])
427
+ assert_equal([[3, 0], [3, 0], Tb::Search::EmptyState], res[1])
428
+ end
429
+
430
+ def test_pat_save_pos
431
+ res = []
432
+ Tb::Search.each_match(
433
+ [:cat, "a", [:save_pos, :n]],
434
+ [%w[a b a a b b]]) {|spos, epos, cap|
435
+ res << [spos, epos, cap]
436
+ }
437
+ assert_equal(3, res.size)
438
+ assert_equal([[0, 0], [0, 0], Tb::Search::State.make(:n => [0,0])], res[0])
439
+ assert_equal([[2, 0], [2, 0], Tb::Search::State.make(:n => [2,0])], res[1])
440
+ assert_equal([[3, 0], [3, 0], Tb::Search::State.make(:n => [3,0])], res[2])
441
+ end
442
+
443
+ def test_pat_push_pos
444
+ res = []
445
+ Tb::Search.each_match(
446
+ [:rep1, "a", [:push_pos, :n], :e],
447
+ [%w[a b a a b b]]) {|spos, epos, cap|
448
+ res << [spos, epos, cap]
449
+ }
450
+ assert_equal(4, res.size)
451
+ assert_equal([[0, 0], [1, 0], Tb::Search::State.make(:n => [[0,0]])], res[0])
452
+ assert_equal([[2, 0], [4, 0], Tb::Search::State.make(:n => [[2,0],[3,0]])], res[1])
453
+ assert_equal([[2, 0], [3, 0], Tb::Search::State.make(:n => [[2,0]])], res[2])
454
+ assert_equal([[3, 0], [4, 0], Tb::Search::State.make(:n => [[3,0]])], res[3])
455
+ end
456
+
457
+ def test_pat_pop_pos
458
+ res = []
459
+ Tb::Search.each_match(
460
+ [:cat, [:push_pos, :n], "a", :e, "b", [:pop_pos, :n]],
461
+ [%w[a b a a b b]]) {|spos, epos, cap|
462
+ res << [spos, epos, cap]
463
+ }
464
+ assert_equal(2, res.size)
465
+ assert_equal([[0, 0], [0, 0], Tb::Search::State.make(:n => [])], res[0])
466
+ assert_equal([[3, 0], [3, 0], Tb::Search::State.make(:n => [])], res[1])
467
+ end
468
+
469
+ def test_pat_update
470
+ res = []
471
+ Tb::Search.each_match(
472
+ [:cat,
473
+ [:capval, :n],
474
+ [:update, lambda {|st| st.merge(:n => st[:n].succ) }],
475
+ :e,
476
+ [:refval, :n]],
477
+ [%w[a a b b b c]]) {|spos, epos, cap|
478
+ res << [spos, epos, cap]
479
+ }
480
+ assert_equal(2, res.size)
481
+ assert_equal([[1, 0], [2, 0], Tb::Search::State.make(:n => "b")], res[0])
482
+ assert_equal([[4, 0], [5, 0], Tb::Search::State.make(:n => "c")], res[1])
483
+ end
484
+
485
+ def test_pat_assert
486
+ res = []
487
+ Tb::Search.each_match(
488
+ [:cat,
489
+ [:capval, :n],
490
+ [:assert, lambda {|st| st[:n] == 'a' }]],
491
+ [%w[a a b b b c]]) {|spos, epos, cap|
492
+ res << [spos, epos, cap]
493
+ }
494
+ assert_equal(2, res.size)
495
+ assert_equal([[0, 0], [0, 0], Tb::Search::State.make(:n => "a")], res[0])
496
+ assert_equal([[1, 0], [1, 0], Tb::Search::State.make(:n => "a")], res[1])
497
+ end
498
+
499
+ def test_pat_invalid_tag_in_array
500
+ assert_raise(ArgumentError) {
501
+ Tb::Search.each_match(
502
+ [:foo],
503
+ [%w[a b c]]) {|spos, epos, cap|
504
+ }
505
+ }
506
+ end
507
+
508
+ def test_pat_invalid
509
+ assert_raise(ArgumentError) {
510
+ Tb::Search.each_match(
511
+ Object.new,
512
+ [%w[a b c]]) {|spos, epos, cap|
513
+ }
514
+ }
515
+ end
516
+
517
+ def test_emptystate_to_h
518
+ s = Tb::Search::EmptyState
519
+ assert_equal({}, s.to_h)
520
+ end
521
+
522
+ def test_emptystate_fetch
523
+ s = Tb::Search::EmptyState
524
+ assert_equal("foo", s.fetch(:k) {|k| assert_equal(:k, k); "foo" })
525
+ assert_equal("bar", s.fetch(:k, "bar"))
526
+ if defined? KeyError
527
+ assert_raise(KeyError) { s.fetch(:k) } # Ruby 1.9
528
+ else
529
+ assert_raise(IndexError) { s.fetch(:k) } # Ruby 1.8
530
+ end
531
+ end
532
+
533
+ def test_emptystate_values_at
534
+ s = Tb::Search::EmptyState
535
+ assert_equal([], s.values_at())
536
+ assert_equal([nil, nil, nil], s.values_at(:x, :y, :z))
537
+ end
538
+
539
+ def test_emptystate_keys
540
+ s = Tb::Search::EmptyState
541
+ assert_equal([], s.keys)
542
+ end
543
+
544
+ def test_emptystate_reject
545
+ s = Tb::Search::EmptyState
546
+ assert_equal(Tb::Search::EmptyState, s.reject {|k, v| flunk })
547
+ end
548
+
549
+ def test_emptystate_inspect
550
+ s = Tb::Search::EmptyState
551
+ assert_kind_of(String, s.inspect)
552
+ end
553
+
554
+ def test_state_fetch
555
+ s = Tb::Search::State.make(:k => 1)
556
+ assert_equal(1, s.fetch(:k))
557
+ assert_equal(:foo, s.fetch(:x) {|k| assert_equal(:x, k); :foo })
558
+ if defined? KeyError
559
+ assert_raise(KeyError) { s.fetch(:x) } # Ruby 1.9
560
+ else
561
+ assert_raise(IndexError) { s.fetch(:x) } # Ruby 1.8
562
+ end
563
+ end
564
+
565
+ def test_state_keys
566
+ s = Tb::Search::State.make(:k => 1)
567
+ assert_equal([:k], s.keys)
568
+ end
569
+
570
+ def test_state_inspect
571
+ s = Tb::Search::State.make(:k => 1)
572
+ assert_kind_of(String, s.inspect)
573
+ end
574
+
575
+ end