tb 0.3 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/README +2 -1
  2. data/lib/tb.rb +7 -3
  3. data/lib/tb/basic.rb +1 -1
  4. data/lib/tb/cmd_cat.rb +1 -3
  5. data/lib/tb/cmd_consecutive.rb +4 -6
  6. data/lib/tb/cmd_crop.rb +5 -7
  7. data/lib/tb/cmd_cross.rb +51 -49
  8. data/lib/tb/cmd_cut.rb +2 -6
  9. data/lib/tb/cmd_git_log.rb +20 -11
  10. data/lib/tb/cmd_grep.rb +1 -3
  11. data/lib/tb/cmd_group.rb +18 -44
  12. data/lib/tb/cmd_gsub.rb +2 -4
  13. data/lib/tb/cmd_join.rb +1 -3
  14. data/lib/tb/cmd_ls.rb +8 -15
  15. data/lib/tb/cmd_mheader.rb +3 -4
  16. data/lib/tb/cmd_nest.rb +4 -9
  17. data/lib/tb/cmd_newfield.rb +1 -3
  18. data/lib/tb/cmd_rename.rb +2 -4
  19. data/lib/tb/cmd_shape.rb +2 -3
  20. data/lib/tb/cmd_sort.rb +3 -5
  21. data/lib/tb/cmd_svn_log.rb +3 -5
  22. data/lib/tb/cmd_tar_tvf.rb +2 -4
  23. data/lib/tb/cmd_to_csv.rb +1 -1
  24. data/lib/tb/cmd_unnest.rb +1 -3
  25. data/lib/tb/cmdutil.rb +57 -135
  26. data/lib/tb/csv.rb +11 -54
  27. data/lib/tb/customcmp.rb +41 -0
  28. data/lib/tb/customeq.rb +41 -0
  29. data/lib/tb/enumerable.rb +225 -435
  30. data/lib/tb/enumerator.rb +22 -14
  31. data/lib/tb/ex_enumerable.rb +659 -0
  32. data/lib/tb/ex_enumerator.rb +102 -0
  33. data/lib/tb/fileenumerator.rb +2 -2
  34. data/lib/tb/func.rb +141 -0
  35. data/lib/tb/json.rb +1 -1
  36. data/lib/tb/reader.rb +4 -4
  37. data/lib/tb/search.rb +2 -4
  38. data/lib/tb/zipper.rb +60 -0
  39. data/test/test_cmd_cat.rb +40 -0
  40. data/test/test_cmd_git_log.rb +116 -0
  41. data/test/test_cmd_ls.rb +90 -0
  42. data/test/test_cmd_svn_log.rb +87 -0
  43. data/test/test_cmd_to_csv.rb +14 -0
  44. data/test/test_cmdutil.rb +25 -10
  45. data/test/test_csv.rb +10 -0
  46. data/test/test_customcmp.rb +14 -0
  47. data/test/test_customeq.rb +20 -0
  48. data/test/{test_enumerable.rb → test_ex_enumerable.rb} +181 -3
  49. data/test/test_search.rb +2 -10
  50. data/test/test_tbenum.rb +3 -3
  51. data/test/test_zipper.rb +22 -0
  52. metadata +20 -8
  53. data/lib/tb/enum.rb +0 -294
  54. data/lib/tb/pairs.rb +0 -227
  55. data/test/test_pairs.rb +0 -122
@@ -35,6 +35,15 @@ class TestTbCmdLs < Test::Unit::TestCase
35
35
  end
36
36
  end
37
37
 
38
+ def with_stderr_log
39
+ File.open("log", "w") {|log|
40
+ with_stderr(log) {
41
+ yield
42
+ }
43
+ }
44
+ File.read('log')
45
+ end
46
+
38
47
  def reader_thread(io)
39
48
  Thread.new {
40
49
  r = ''
@@ -199,4 +208,85 @@ class TestTbCmdLs < Test::Unit::TestCase
199
208
  end
200
209
  end
201
210
 
211
+ def test_ls_info_symlink
212
+ lsobj = Tb::Cmd::Ls.new(nil, {})
213
+ st = Object.new
214
+ def st.symlink?() true end
215
+ log = with_stderr_log {
216
+ assert_nil(lsobj.ls_info_symlink('.', st))
217
+ }
218
+ assert(!log.empty?)
219
+ end
220
+
221
+ end
222
+
223
+ class TestTbCmdLsNoTmpDir < Test::Unit::TestCase
224
+ def setup
225
+ Tb::Cmd.reset_option
226
+ #@curdir = Dir.pwd
227
+ #@tmpdir = Dir.mktmpdir
228
+ #Dir.chdir @tmpdir
229
+ end
230
+ def teardown
231
+ Tb::Cmd.reset_option
232
+ #Dir.chdir @curdir
233
+ #FileUtils.rmtree @tmpdir
234
+ end
235
+
236
+ def test_ls_info_filemode
237
+ lsobj = Tb::Cmd::Ls.new(nil, {})
238
+ st = Object.new
239
+ def st.mode() 0 end
240
+ def st.ftype() @ftype end
241
+ def st.ftype=(arg) @ftype = arg end
242
+ st.ftype = 'file'
243
+ assert_equal("----------", lsobj.ls_info_filemode(nil, st))
244
+ st.ftype = 'directory'
245
+ assert_equal("d---------", lsobj.ls_info_filemode(nil, st))
246
+ st.ftype = 'characterSpecial'
247
+ assert_equal("c---------", lsobj.ls_info_filemode(nil, st))
248
+ st.ftype = 'blockSpecial'
249
+ assert_equal("b---------", lsobj.ls_info_filemode(nil, st))
250
+ st.ftype = 'fifo'
251
+ assert_equal("p---------", lsobj.ls_info_filemode(nil, st))
252
+ st.ftype = 'link'
253
+ assert_equal("l---------", lsobj.ls_info_filemode(nil, st))
254
+ st.ftype = 'socket'
255
+ assert_equal("s---------", lsobj.ls_info_filemode(nil, st))
256
+ st.ftype = 'unknown'
257
+ assert_equal("?---------", lsobj.ls_info_filemode(nil, st))
258
+ st.ftype = 'foobar'
259
+ assert_equal("?---------", lsobj.ls_info_filemode(nil, st))
260
+ end
261
+
262
+ def test_ls_info_user
263
+ lsobj = Tb::Cmd::Ls.new(nil, {})
264
+ st = Object.new
265
+ # assumes Etc.getpwuid(-100) causes ArgumentError.
266
+ def st.uid() -100 end
267
+ assert_equal("-100", lsobj.ls_info_user(nil, st))
268
+ end
269
+
270
+ def test_ls_info_group
271
+ lsobj = Tb::Cmd::Ls.new(nil, {})
272
+ st = Object.new
273
+ # assumes Etc.getgrgid(-200) causes ArgumentError.
274
+ def st.gid() -200 end
275
+ assert_equal("-200", lsobj.ls_info_group(nil, st))
276
+ end
277
+
278
+ def test_ls_info_atime
279
+ lsobj = Tb::Cmd::Ls.new(nil, {:l => 1})
280
+ st = Object.new
281
+ def st.atime() Time.utc(2000) end
282
+ assert_equal("2000-01-01T00:00:00Z", lsobj.ls_info_atime(nil, st))
283
+ end
284
+
285
+ def test_ls_info_ctime
286
+ lsobj = Tb::Cmd::Ls.new(nil, {:l => 1})
287
+ st = Object.new
288
+ def st.ctime() Time.utc(2000) end
289
+ assert_equal("2000-01-01T00:00:00Z", lsobj.ls_info_ctime(nil, st))
290
+ end
291
+
202
292
  end
@@ -0,0 +1,87 @@
1
+ require 'test/unit'
2
+ require 'tb/cmdtop'
3
+ require 'tmpdir'
4
+
5
+ class TestTbCmdSvnLog < Test::Unit::TestCase
6
+ def setup
7
+ Tb::Cmd.reset_option
8
+ @curdir = Dir.pwd
9
+ @tmpdir = Dir.mktmpdir
10
+ Dir.chdir @tmpdir
11
+ end
12
+ def teardown
13
+ Tb::Cmd.reset_option
14
+ Dir.chdir @curdir
15
+ FileUtils.rmtree @tmpdir
16
+ end
17
+
18
+ def with_stderr(io)
19
+ save = $stderr
20
+ $stderr = io
21
+ begin
22
+ yield
23
+ ensure
24
+ $stderr = save
25
+ end
26
+ end
27
+
28
+ def test_basic
29
+ system("svnadmin create repo")
30
+ system("svn co -q file://#{@tmpdir}/repo .")
31
+ File.open("foo", "w") {|f| f.puts "bar" }
32
+ File.open("hoge", "w") {|f| f.puts "moge" }
33
+ system("svn add -q foo hoge")
34
+ system("svn commit -q -m baz foo hoge")
35
+ system("svn update -q") # update the revision of the directory.
36
+ Tb::Cmd.main_svn_log(['-o', o="o.csv"])
37
+ result = File.read(o)
38
+ tb = Tb.parse_csv(result)
39
+ assert_equal(1, tb.size)
40
+ assert_match(/baz/, tb.get_record(0)["msg"])
41
+ end
42
+
43
+ def test_verbose
44
+ system("svnadmin create repo")
45
+ system("svn co -q file://#{@tmpdir}/repo .")
46
+ File.open("foo", "w") {|f| f.puts "bar" }
47
+ File.open("hoge", "w") {|f| f.puts "moge" }
48
+ system("svn add -q foo hoge")
49
+ system("svn commit -q -m baz foo hoge")
50
+ system("svn update -q") # update the revision of the directory.
51
+ Tb::Cmd.main_svn_log(['-o', o="o.csv", '--', '-v'])
52
+ result = File.read(o)
53
+ tb = Tb.parse_csv(result)
54
+ assert_equal(2, tb.size)
55
+ recs = [tb.get_record(0), tb.get_record(1)]
56
+ recs = recs.sort_by {|rec| rec['path'] }
57
+ recs.each {|rec|
58
+ assert_match(/baz/, rec["msg"])
59
+ }
60
+ assert_match(/foo/, recs[0]["path"])
61
+ assert_match(/hoge/, recs[1]["path"])
62
+ end
63
+
64
+ def test_log_xml
65
+ system("svnadmin create repo")
66
+ system("svn co -q file://#{@tmpdir}/repo .")
67
+ File.open("foo", "w") {|f| f.puts "bar" }
68
+ File.open("hoge", "w") {|f| f.puts "moge" }
69
+ system("svn add -q foo hoge")
70
+ system("svn commit -q -m baz foo hoge")
71
+ system("svn update -q") # update the revision of the directory.
72
+ ###
73
+ Tb::Cmd.main_svn_log(['-o', o="o.csv"])
74
+ result = File.read(o)
75
+ tb = Tb.parse_csv(result)
76
+ assert_equal(1, tb.size)
77
+ assert_match(/baz/, tb.get_record(0)["msg"])
78
+ ###
79
+ system("svn log --xml > log.xml")
80
+ FileUtils.rmtree('.svn')
81
+ Tb::Cmd.main_svn_log(['-o', o="o.csv", '--svn-log-xml=log.xml'])
82
+ result = File.read(o)
83
+ tb = Tb.parse_csv(result)
84
+ assert_equal(1, tb.size)
85
+ assert_match(/baz/, tb.get_record(0)["msg"])
86
+ end
87
+ end
@@ -140,4 +140,18 @@ class TestTbCmdToCSV < Test::Unit::TestCase
140
140
  End
141
141
  end
142
142
 
143
+ def test_output_extension
144
+ File.open(i="i.tsv", "w") {|f| f << <<-"End".gsub(/^[ \t]+/, '') }
145
+ a\tb\tc
146
+ 0\t1\t2
147
+ 4\t5\t6
148
+ End
149
+ Tb::Cmd.main_to_csv(['-o', o="o.json", i])
150
+ assert_equal(<<-"End".gsub(/^[ \t]+/, ''), File.read(o))
151
+ a,b,c
152
+ 0,1,2
153
+ 4,5,6
154
+ End
155
+ end
156
+
143
157
  end
@@ -26,18 +26,33 @@ class TestTbCmdUtil < Test::Unit::TestCase
26
26
  end
27
27
 
28
28
  def test_smart_cmp_value
29
- assert_equal(0, smart_cmp_value(0) <=> smart_cmp_value(0))
30
- assert_equal(1, smart_cmp_value(10) <=> smart_cmp_value(0))
31
- assert_equal(-1, smart_cmp_value(-10) <=> smart_cmp_value(0))
32
- assert_equal(0, smart_cmp_value("a") <=> smart_cmp_value("a"))
33
- assert_equal(1, smart_cmp_value("z") <=> smart_cmp_value("a"))
34
- assert_equal(-1, smart_cmp_value("a") <=> smart_cmp_value("b"))
35
- assert_equal(1, smart_cmp_value("08") <=> smart_cmp_value("7"))
36
- assert_raise(ArgumentError) { smart_cmp_value(Object.new) }
29
+ assert_equal(0, Tb::Func.smart_cmp_value(0) <=> Tb::Func.smart_cmp_value(0))
30
+ assert_equal(1, Tb::Func.smart_cmp_value(10) <=> Tb::Func.smart_cmp_value(0))
31
+ assert_equal(-1, Tb::Func.smart_cmp_value(-10) <=> Tb::Func.smart_cmp_value(0))
32
+ assert_equal(0, Tb::Func.smart_cmp_value("a") <=> Tb::Func.smart_cmp_value("a"))
33
+ assert_equal(1, Tb::Func.smart_cmp_value("z") <=> Tb::Func.smart_cmp_value("a"))
34
+ assert_equal(-1, Tb::Func.smart_cmp_value("a") <=> Tb::Func.smart_cmp_value("b"))
35
+ assert_equal(1, Tb::Func.smart_cmp_value("08") <=> Tb::Func.smart_cmp_value("7"))
36
+ assert_raise(ArgumentError) { Tb::Func.smart_cmp_value(Object.new) }
37
37
  end
38
38
 
39
- def test_conv_to_numeric
40
- assert_raise(ArgumentError) { conv_to_numeric("foo") }
39
+ def test_parse_aggregator_spec2
40
+ assert_raise(ArgumentError) { parse_aggregator_spec2("foo") }
41
+ end
42
+
43
+ def test_with_output_preserve_mtime
44
+ Dir.mktmpdir {|d|
45
+ fn = "#{d}/a"
46
+ File.open(fn, "w") {|f| f.print "foo" }
47
+ t0 = Time.utc(2000)
48
+ File.utime(t0, t0, fn)
49
+ t1 = File.stat(fn).mtime
50
+ with_output(fn) {|f|
51
+ f.print "foo"
52
+ }
53
+ t2 = File.stat(fn).mtime
54
+ assert_equal(t1, t2)
55
+ }
41
56
  end
42
57
 
43
58
  end
@@ -65,6 +65,16 @@ class TestTbCSV < Test::Unit::TestCase
65
65
  End
66
66
  end
67
67
 
68
+ def test_generate_without_explicit_fields
69
+ t = Tb.new %w[a b], [1, 2], [3, 4]
70
+ out = t.generate_csv('')
71
+ assert_equal(<<-'End'.gsub(/^\s+/, ''), out)
72
+ a,b
73
+ 1,2
74
+ 3,4
75
+ End
76
+ end
77
+
68
78
  def test_generate_with_block
69
79
  t = Tb.new %w[a b], [1, 2], [3, 4]
70
80
  out = t.generate_csv('', ['a', 'b']) {|recids| recids.reverse }
@@ -0,0 +1,14 @@
1
+ require 'tb'
2
+ require 'test/unit'
3
+
4
+ class TestCustomCmp < Test::Unit::TestCase
5
+ def test_revcmp
6
+ cmp = lambda {|a, b| b <=> a }
7
+ v1 = Tb::CustomCmp.new(1, &cmp)
8
+ v2 = Tb::CustomCmp.new(2, &cmp)
9
+ v3 = Tb::CustomCmp.new(3, &cmp)
10
+ assert_equal(2 <=> 1, v1 <=> v2)
11
+ assert_equal(1 <=> 2, v2 <=> v1)
12
+ assert_equal(3 <=> 3, v3 <=> v3)
13
+ end
14
+ end
@@ -0,0 +1,20 @@
1
+ require 'tb'
2
+ require 'test/unit'
3
+
4
+ class TestCustomEq < Test::Unit::TestCase
5
+ def test_decreasing
6
+ rel = lambda {|a, b| a > b }
7
+ v1 = Tb::CustomEq.new(1, &rel)
8
+ v2 = Tb::CustomEq.new(2, &rel)
9
+ v3 = Tb::CustomEq.new(3, &rel)
10
+ assert_equal(false, v1 == v1)
11
+ assert_equal(false, v1 == v2)
12
+ assert_equal(false, v1 == v3)
13
+ assert_equal(true, v2 == v1)
14
+ assert_equal(false, v2 == v2)
15
+ assert_equal(false, v2 == v3)
16
+ assert_equal(true, v3 == v1)
17
+ assert_equal(true, v3 == v2)
18
+ assert_equal(false, v3 == v3)
19
+ end
20
+ end
@@ -173,10 +173,84 @@ class TestTbEnumerable < Test::Unit::TestCase
173
173
  }
174
174
  end
175
175
 
176
- def test_each_group_element
176
+ def test_extsort_by_map
177
+ assert_equal([20,12,13],
178
+ [10,2,3].extsort_by(:map => lambda {|v| v + 10 }) {|v| v.to_s }.to_a)
179
+ end
180
+
181
+ def test_extsort_by_unique
182
+ [
183
+ [[1,1], [2]],
184
+ [[1,2,1], [2,2]],
185
+ [[1,2,3,2,1], [2,4,3]],
186
+ [[1,1,2,2,3], [2,4,3]]
187
+ ].each {|ary, result|
188
+ [nil, 0].each {|memsize|
189
+ assert_equal(result,
190
+ ary.extsort_by(:memsize => memsize,
191
+ :unique => lambda {|x,y| x + y }) {|x| x }.to_a)
192
+ }
193
+ }
194
+ end
195
+
196
+ def test_extsort_by_unique_random
197
+ [nil, 0].each {|memsize|
198
+ 3.times {|i|
199
+ len = rand(100)
200
+ ary = []
201
+ len.times { ary << rand(100) }
202
+ h = ary.group_by {|v| v }
203
+ ary1 = h.keys.sort.map {|k| h[k].inject(&:+) }
204
+ ary2 = ary.extsort_by(:memsize => memsize,
205
+ :unique => lambda {|x, y| x + y }) {|v| v }.to_a
206
+ assert_equal(ary1, ary2)
207
+ }
208
+ }
209
+ end
210
+
211
+ def test_extsort_reduce
212
+ result = [
213
+ [:cat, 1],
214
+ [:dog, 2],
215
+ [:cat, 3],
216
+ [:dog, 1],
217
+ ].extsort_reduce(:+.to_proc) {|pair| pair }.to_a
218
+ assert_equal([[:cat, 4], [:dog, 3]], result)
219
+ end
220
+
221
+ def test_each_group_element_by_customeq
222
+ result = []
223
+ (0..9).to_a.each_group_element_by(
224
+ lambda {|v| Tb::CustomEq.new(v) {|a, b| a / 3 == b / 3 } },
225
+ lambda {|v| result << [:before, v] },
226
+ lambda {|v| result << [:body, v] },
227
+ lambda {|v| result << [:after, v] })
228
+ assert_equal(
229
+ [[:before, 0],
230
+ [:body, 0],
231
+ [:body, 1],
232
+ [:body, 2],
233
+ [:after, 2],
234
+ [:before, 3],
235
+ [:body, 3],
236
+ [:body, 4],
237
+ [:body, 5],
238
+ [:after, 5],
239
+ [:before, 6],
240
+ [:body, 6],
241
+ [:body, 7],
242
+ [:body, 8],
243
+ [:after, 8],
244
+ [:before, 9],
245
+ [:body, 9],
246
+ [:after, 9]],
247
+ result)
248
+ end
249
+
250
+ def test_each_group_element_by
177
251
  result = []
178
- (0..9).to_a.each_group_element(
179
- lambda {|a, b| a / 3 != b / 3 },
252
+ (0..9).to_a.each_group_element_by(
253
+ lambda {|v| v / 3 },
180
254
  lambda {|v| result << [:before, v] },
181
255
  lambda {|v| result << [:body, v] },
182
256
  lambda {|v| result << [:after, v] })
@@ -201,4 +275,108 @@ class TestTbEnumerable < Test::Unit::TestCase
201
275
  [:after, 9]],
202
276
  result)
203
277
  end
278
+
279
+ def test_detect_group_by
280
+ enum = (0..9).to_a
281
+ result = []
282
+ e3 = enum.detect_group_by(
283
+ lambda {|elt| result << [:before, 3, elt] },
284
+ lambda {|elt| result << [:after, 3, elt] }) {|elt|
285
+ elt / 3
286
+ }
287
+ e4 = e3.detect_group_by(
288
+ lambda {|elt| result << [:before, 4, elt] },
289
+ lambda {|elt| result << [:after, 4, elt] }) {|elt|
290
+ elt / 4
291
+ }
292
+ e4.each {|elt|
293
+ result << [:body, elt]
294
+ }
295
+ assert_equal(
296
+ [[:before, 3, 0],
297
+ [:before, 4, 0],
298
+ [:body, 0],
299
+ [:body, 1],
300
+ [:body, 2],
301
+ [:after, 3, 2],
302
+ [:before, 3, 3],
303
+ [:body, 3],
304
+ [:after, 4, 3],
305
+ [:before, 4, 4],
306
+ [:body, 4],
307
+ [:body, 5],
308
+ [:after, 3, 5],
309
+ [:before, 3, 6],
310
+ [:body, 6],
311
+ [:body, 7],
312
+ [:after, 4, 7],
313
+ [:before, 4, 8],
314
+ [:body, 8],
315
+ [:after, 3, 8],
316
+ [:before, 3, 9],
317
+ [:body, 9],
318
+ [:after, 3, 9],
319
+ [:after, 4, 9]],
320
+ result)
321
+ end
322
+
323
+ def test_detect_nested_group_by_simple
324
+ assert_equal([], [].detect_nested_group_by([]).to_a)
325
+ assert_equal([1], [1].detect_nested_group_by([]).to_a)
326
+
327
+ result = []
328
+ [].detect_nested_group_by(
329
+ [[lambda {|v| v.even? },
330
+ lambda {|v| result << [:s, v] },
331
+ lambda {|v| result << [:e, v] }]]).each {|v| result << v }
332
+ assert_equal([], result)
333
+ end
334
+
335
+ def test_detect_nested_group_by
336
+ enum = (0..9).to_a
337
+ result = []
338
+ e = enum.detect_nested_group_by(
339
+ [[lambda {|elt| elt / 3 },
340
+ lambda {|elt| result << [:before, 3, elt] },
341
+ lambda {|elt| result << [:after, 3, elt] }],
342
+ [lambda {|elt| elt / 4 },
343
+ lambda {|elt| result << [:before, 4, elt] },
344
+ lambda {|elt| result << [:after, 4, elt] }]])
345
+ e.each {|elt|
346
+ result << [:body, elt]
347
+ }
348
+ assert_equal(
349
+ [[:before, 3, 0],
350
+ [:before, 4, 0],
351
+ [:body, 0],
352
+ [:body, 1],
353
+ [:body, 2],
354
+ [:after, 4, 2],
355
+ [:after, 3, 2],
356
+ [:before, 3, 3],
357
+ [:before, 4, 3],
358
+ [:body, 3],
359
+ [:after, 4, 3],
360
+ [:before, 4, 4],
361
+ [:body, 4],
362
+ [:body, 5],
363
+ [:after, 4, 5],
364
+ [:after, 3, 5],
365
+ [:before, 3, 6],
366
+ [:before, 4, 6],
367
+ [:body, 6],
368
+ [:body, 7],
369
+ [:after, 4, 7],
370
+ [:before, 4, 8],
371
+ [:body, 8],
372
+ [:after, 4, 8],
373
+ [:after, 3, 8],
374
+ [:before, 3, 9],
375
+ [:before, 4, 9],
376
+ [:body, 9],
377
+ [:after, 4, 9],
378
+ [:after, 3, 9]],
379
+ result)
380
+ end
381
+
204
382
  end