gr8 0.1.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.
@@ -0,0 +1,277 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ ###
4
+ ### $Release: 0.1.0 $
5
+ ### $Copyright: copyright(c) 2015 kuwata-lab.com all rights reserved $
6
+ ### $License: MIT License $
7
+ ###
8
+
9
+ require_relative "common"
10
+ require "oktest"
11
+
12
+
13
+ Oktest.scope do
14
+
15
+
16
+ topic Gr8::App do
17
+
18
+ fixture :app do
19
+ app = Gr8::App.new
20
+ app.instance_variable_set('@script_name', "gr8")
21
+ app
22
+ end
23
+
24
+ fixture :input_data do
25
+ <<END
26
+ Haruhi 100
27
+ Mikuru 80
28
+ Yuki 120
29
+ END
30
+ end
31
+
32
+
33
+ topic '#run()' do
34
+
35
+ spec "[!33bj3] option '-h', '--help': prints help message." do
36
+ |app|
37
+ expected = Gr8::HELP % {script: "gr8"}
38
+ #
39
+ status = nil
40
+ sout, serr = dummy_io { status = app.run("-h") }
41
+ ok {sout} == expected
42
+ ok {serr} == ""
43
+ ok {status} == 0
44
+ #
45
+ status = nil
46
+ sout, serr = dummy_io { status = app.run("--help") }
47
+ ok {sout} == expected
48
+ ok {serr} == ""
49
+ ok {status} == 0
50
+ end
51
+
52
+ spec "[!7dvjg] option '--doc': opens website with browser." do
53
+ skip_when true, "hard to test"
54
+ end
55
+
56
+ spec "[!2tfh5] option '-v', '--version': prints version string." do
57
+ |app|
58
+ expected = Gr8::VERSION + "\n"
59
+ #
60
+ status = nil
61
+ sout, serr = dummy_io { status = app.run("-v") }
62
+ ok {sout} == expected
63
+ ok {serr} == ""
64
+ ok {status} == 0
65
+ #
66
+ status = nil
67
+ sout, serr = dummy_io { status = app.run("--version") }
68
+ ok {sout} == expected
69
+ ok {serr} == ""
70
+ ok {status} == 0
71
+ end
72
+
73
+ spec "[!1s7wm] option '-r': requires libraries." do
74
+ |app|
75
+ ok {defined?(PStore)} == nil
76
+ ok {defined?(GetoptLong)} == nil
77
+ dummy_io { app.run("-r pstore,getoptlong", "map{|s| s}") }
78
+ ok {defined?(PStore)} == "constant"
79
+ ok {defined?(GetoptLong)} == "constant"
80
+ end
81
+
82
+ spec "[!7wqyh] prints error when no argument." do
83
+ |app|
84
+ status = nil
85
+ sout, serr = dummy_io { status = app.run() }
86
+ ok {sout} == ""
87
+ ok {serr} == "ERROR (gr8): argument required.\n"
88
+ ok {status} == 1
89
+ end
90
+
91
+ spec "[!bwiqv] prints error when too many argument." do
92
+ |app|
93
+ status = nil
94
+ sout, serr = dummy_io { status = app.run("a", "b") }
95
+ ok {sout} == ""
96
+ ok {serr} == "ERROR (gr8): too many arguments.\n"
97
+ ok {status} == 1
98
+ end
99
+
100
+ spec "[!r69d6] executes ruby code with $stdin.lazy as self." do
101
+ |app, input_data|
102
+ code = "map{|s| s.split()[1].to_i}.inject(0,:+)"
103
+ status = nil
104
+ sout, serr = dummy_io(input_data) { status = app.run(code) }
105
+ ok {sout} == "300\n"
106
+ ok {serr} == ""
107
+ ok {status} == 0
108
+ #
109
+ code = "self.is_a?(Enumerator::Lazy)"
110
+ sout, serr = dummy_io(input_data) { app.run(code) }
111
+ ok {sout} == "true\n"
112
+ end
113
+
114
+ spec "[!zcxh1] removes '\n' from each line automatically." do
115
+ |app, input_data|
116
+ expected = <<'END'
117
+ "Haruhi 100"
118
+ "Mikuru 80"
119
+ "Yuki 120"
120
+ END
121
+ code = "map{|s| s.inspect }"
122
+ sout, _ = dummy_io(input_data) { app.run(code) }
123
+ ok {sout} == expected
124
+ end
125
+
126
+ spec "[!i7npb] $1, $2, ... are available in grep() block argument." do
127
+ |app, input_data|
128
+ code = 'grep(/^(\w+)\s+(\d+)$/){$1}'
129
+ sout, _ = dummy_io(input_data) { app.run(code) }
130
+ ok {sout} == "Haruhi\nMikuru\nYuki\n"
131
+ #
132
+ code = 'grep(/^(\w+)\s+(\d+)$/){$2.to_i}.inject(0,:+)'
133
+ sout, _ = dummy_io(input_data) { app.run(code) }
134
+ ok {sout} == "300\n"
135
+ end
136
+
137
+ spec "[!vkt64] lines are chomped automatically in grep() if block is not given." do
138
+ |app, input_data|
139
+ code = 'grep(/\d+/).map{|s| s.inspect}'
140
+ sout, _ = dummy_io(input_data) { app.run(code) }
141
+ ok {sout} == <<'END'
142
+ "Haruhi 100"
143
+ "Mikuru 80"
144
+ "Yuki 120"
145
+ END
146
+ end
147
+
148
+ spec "[!8hk3g] option '-F': separates each line into array." do
149
+ |app|
150
+ input_data = "A:10:x\n" + "B:20:y\n" + "C:30:z\n"
151
+ code = "map{|s| s.inspect }"
152
+ status = nil
153
+ sout, serr = dummy_io(input_data) { status = app.run("-F:", code) }
154
+ ok {sout} == %Q`["A", "10", "x"]\n["B", "20", "y"]\n["C", "30", "z"]\n`
155
+ ok {serr} == ""
156
+ ok {status} == 0
157
+ end
158
+
159
+ spec "[!jt4y5] option '-F': separator is omissible." do
160
+ |app, input_data|
161
+ code = "map{|s| s.inspect }"
162
+ status = nil
163
+ sout, serr = dummy_io(input_data) { status = app.run("-F", code) }
164
+ ok {sout} == %Q`["Haruhi", "100"]\n["Mikuru", "80"]\n["Yuki", "120"]\n`
165
+ ok {serr} == ""
166
+ ok {status} == 0
167
+ end
168
+
169
+ spec "[!jo4gm] option '-F': error when invalid regular expression." do
170
+ |app, input_data|
171
+ code = "map{|s| s.inspect }"
172
+ status = nil
173
+ sout, serr = dummy_io(input_data) { status = app.run("-F[a-}", code) }
174
+ ok {sout} == ""
175
+ ok {serr} == "ERROR (gr8): invalid regular expression: -F[a-}\n"
176
+ ok {status} == 1
177
+ end
178
+
179
+ spec "[!vnwu6] option '-C': select colum." do
180
+ |app, input_data|
181
+ code = "map{|s| s.inspect }"
182
+ sout, serr = dummy_io(input_data) { app.run("-C2", code) }
183
+ ok {sout} == %Q`"100"\n"80"\n"120"\n`
184
+ ok {serr} == ""
185
+ end
186
+
187
+ spec "[!7ruq0] option -C: argument should be an integer." do
188
+ |app, input_data|
189
+ code = "map{|s| s.inspect }"
190
+ status = nil
191
+ sout, serr = dummy_io(input_data) { status = app.run("-Cx", code) }
192
+ ok {sout} == ""
193
+ ok {serr} == "ERROR (gr8): integer expected: -Cx\n"
194
+ ok {status} == 1
195
+ end
196
+
197
+ spec "[!6x3dp] option -C: argument should be >= 1." do
198
+ |app, input_data|
199
+ code = "map{|s| s.inspect }"
200
+ status = nil
201
+ sout, serr = dummy_io(input_data) { status = app.run("-C0", code) }
202
+ ok {sout} == ""
203
+ ok {serr} == "ERROR (gr8): column number should be >= 1: -C0\n"
204
+ ok {status} == 1
205
+ end
206
+
207
+ spec "[!hsvnd] prints nothing when result is nil." do
208
+ |app, input_data|
209
+ sout, serr = dummy_io(input_data) { app.run("nil") }
210
+ ok {sout} == ""
211
+ ok {serr} == ""
212
+ end
213
+
214
+ spec "[!eiaa6] prints each item when result is Enumerable." do
215
+ |app, input_data|
216
+ sout, serr = dummy_io(input_data) { app.run("[10, 20, 30]") }
217
+ ok {sout} == "10\n20\n30\n"
218
+ ok {serr} == ""
219
+ end
220
+
221
+ spec "[!6pfay] prints value when result is not nil nor Enumerable." do
222
+ |app, input_data|
223
+ sout, serr = dummy_io(input_data) { app.run("123") }
224
+ ok {sout} == "123\n"
225
+ ok {serr} == ""
226
+ end
227
+
228
+ spec "[!h5wln] returns 0 as status code when executed successfully." do
229
+ |app, input_data|
230
+ code = "map{|s| s.split[1]}.map(&:to_i).inject(0,:+)"
231
+ status = nil
232
+ sout, serr = dummy_io(input_data) { status = app.run(code) }
233
+ ok {status} == 0
234
+ ok {sout} == "300\n"
235
+ ok {serr} == ""
236
+ end
237
+
238
+ end
239
+
240
+
241
+ topic '#main()' do
242
+
243
+ spec "[!w9kb8] exit with status code 0 when executed successfully." do
244
+ |app|
245
+ skip_when true, "contains exit()"
246
+ end
247
+
248
+ spec "[!nbag1] exit with status code 1 when execution failed." do
249
+ |app|
250
+ skip_when true, "contains exit()"
251
+ end
252
+
253
+ end
254
+
255
+
256
+ topic '#parse_options()' do
257
+
258
+ spec "[!5efp5] returns Hash object containing command-line options." do
259
+ args = ["-h", "--version", "arg1", "arg2"]
260
+ opts = Gr8::App.new.__send__(:parse_options, args)
261
+ ok {opts}.is_a?(Hash)
262
+ ok {opts} == {help: true, version: true}
263
+ end
264
+
265
+ spec "[!wdzss] modifies args." do
266
+ args = ["-h", "--version", "arg1", "arg2"]
267
+ opts = Gr8::App.new.__send__(:parse_options, args)
268
+ ok {args} == ["arg1", "arg2"]
269
+ end
270
+
271
+ end
272
+
273
+
274
+ end
275
+
276
+
277
+ end
@@ -0,0 +1,31 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ ###
4
+ ### $Release: 0.1.0 $
5
+ ### $Copyright: copyright(c) 2015 kuwata-lab.com all rights reserved $
6
+ ### $License: MIT License $
7
+ ###
8
+
9
+ $: << File.dirname(__FILE__)
10
+
11
+ require "stringio"
12
+
13
+ $DONT_RUN_GR8_APP = true
14
+ unless defined?(Gr8)
15
+ File.class_eval do
16
+ load join(dirname(dirname(__FILE__)), "bin", "gr8")
17
+ end
18
+ end
19
+
20
+
21
+ def dummy_io(input=nil)
22
+ originals = [$stdin, $stdout, $stderr]
23
+ sin, sout, serr = StringIO.new(input.to_s), StringIO.new, StringIO.new
24
+ $stdin, $stdout, $stderr = sin, sout, serr
25
+ begin
26
+ yield
27
+ ensure
28
+ $stdin, $stdout, $stderr = originals
29
+ end
30
+ return sout.string, serr.string
31
+ end
@@ -0,0 +1,834 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ ###
4
+ ### $Release: 0.1.0 $
5
+ ### $Copyright: copyright(c) 2015 kuwata-lab.com all rights reserved $
6
+ ### $License: MIT License $
7
+ ###
8
+
9
+ require_relative "common"
10
+ require "oktest"
11
+
12
+
13
+ Oktest.scope do
14
+
15
+
16
+ topic Enumerable do
17
+
18
+
19
+ topic '#transform()' do
20
+
21
+ spec "[!peitw] similar to map() or collect(), make each item as self in block." do
22
+ ok { (1..3).xf {|i| i*10 } } == [10, 20, 30]
23
+ ok { (1..3).xf {|i| self*10 } } == [10, 20, 30]
24
+ end
25
+
26
+ end
27
+
28
+
29
+ topic '#map()' do
30
+
31
+ spec "[!zfmcx] each item is available as self in block of map()." do
32
+ ok { (1..3).map {|i| i * 10} } == [10, 20, 30]
33
+ ok { (1..3).map {|i| self*10} } == [10, 20, 30]
34
+ end
35
+
36
+ end
37
+
38
+
39
+ topic '#select()' do
40
+
41
+ spec "[!41hap] each item is available as self in block of select()." do
42
+ ok { (1..5).select {|i| i % 2 == 0 } } == [2, 4]
43
+ ok { (1..5).select {|i| self % 2 == 0 } } == [2, 4]
44
+ end
45
+
46
+ end
47
+
48
+
49
+ topic '#sum()' do
50
+
51
+ spec "[!9izc1] returns sum of numbers." do
52
+ ok {[0, 10, 20, 30].sum} == 60
53
+ ok {[0, 10, 20, 30].sum}.is_a?(Fixnum)
54
+ ok {[0.0, 10, 20, 30].sum} == 60.0
55
+ ok {[0.0, 10, 20, 30].sum}.is_a?(Float)
56
+ end
57
+
58
+ end
59
+
60
+
61
+ topic '#sum_i()' do
62
+
63
+ spec "[!01ehd] returns sum of integers, converting values into integer." do
64
+ ok {["10", "20", "30"].sum_i} == 60
65
+ ok {["10", "20", "30"].sum_i}.is_a?(Fixnum)
66
+ ok {["10.0", "20.0", "30.0"].sum_i} == 60
67
+ ok {["10.0", "20.0", "30.0"].sum_i}.is_a?(Fixnum)
68
+ end
69
+
70
+ end
71
+
72
+
73
+ topic '#sum_f()' do
74
+
75
+ spec "[!kplnt] returns sum of floats, converting values into float." do
76
+ ok {["10.5", "20.5", "30.5"].sum_f} == 61.5
77
+ ok {["10.5", "20.5", "30.5"].sum_f}.is_a?(Float)
78
+ ok {["10", "20", "30"].sum_f} == 60.0
79
+ ok {["10", "20", "30"].sum_f}.is_a?(Float)
80
+ end
81
+
82
+ end
83
+
84
+
85
+ topic '#avg()' do
86
+
87
+ spec "[!pvi8h] returnns average of numbers." do
88
+ ok {[10, 20, 30].avg} == 20.0
89
+ end
90
+
91
+ spec "[!poidi] returns nil when no numbers." do
92
+ ok {[].avg} == nil
93
+ end
94
+
95
+ end
96
+
97
+
98
+ topic '#avg_i()' do
99
+
100
+ spec "[!btiat] returns average of numbers, converting values into integer." do
101
+ ok {["10", "20", "30"].avg_i} == 20.0
102
+ ok {["10.1", "20.2", "30.3"].avg_i} == 20.0
103
+ end
104
+
105
+ spec "[!892q9] returns nil when no numbers." do
106
+ ok {[].avg_i} == nil
107
+ end
108
+
109
+ end
110
+
111
+
112
+ topic '#avg_f()' do
113
+
114
+ spec "[!oqpmc] returns average of numbers, converting values into float." do
115
+ ok {["10", "20", "30"].avg_f} == 20.0
116
+ ok {["10.1", "20.2", "30.3"].avg_f} == 20.2
117
+ end
118
+
119
+ spec "[!9bckq] returns nil when no numbers." do
120
+ ok {[].avg_f} == nil
121
+ end
122
+
123
+ end
124
+
125
+
126
+ topic '#xsplit()' do
127
+
128
+ spec "[!1pz77] splits each lines with pattern." do
129
+ arr = [" A 10\n", " B 20\n", " C 30\n"]
130
+ ok {arr.xsplit} == [["A", "10"], ["B", "20"], ["C", "30"]]
131
+ arr = [" A: 10\n", " B: 20\n", " C: 30\n"]
132
+ ok {arr.xsplit(/:/)} == [[" A", " 10\n"], [" B", " 20\n"], [" C", " 30\n"]]
133
+ end
134
+
135
+ spec "[!wte7b] if block given, use its result as index." do
136
+ arr = [" A 10\n", " B 20\n", " C 30\n"]
137
+ ok {arr.xsplit{1}} == ["10", "20", "30"]
138
+ arr = [" A: 10\n", " B: 20\n", " C: 30\n"]
139
+ ok {arr.xsplit(/:/){0}} == [" A", " B", " C"]
140
+ end
141
+
142
+ end
143
+
144
+
145
+ topic '#sed()' do
146
+
147
+ spec "[!c7m34] replaces all patterns found in each line with str or block." do
148
+ arr = ["a100", "b200", "c300"]
149
+ ok {arr.sed(/0/, '*')} == ["a1*0", "b2*0", "c3*0"]
150
+ ok {arr.sed(/[a-z]/){|s| s.upcase}} == ["A100", "B200", "C300"]
151
+ end
152
+
153
+ end
154
+
155
+
156
+ topic '#gsed()' do
157
+
158
+ spec "[!9lzjv] replaces first pattern found in each line with str or block." do
159
+ arr = ["a100", "b200", "c300"]
160
+ ok {arr.gsed(/0/, '*')} == ["a1**", "b2**", "c3**"]
161
+ ok {arr.gsed(/[a-z]/){|s| s.upcase}} == ["A100", "B200", "C300"]
162
+ end
163
+
164
+ end
165
+
166
+
167
+ topic '#paths()' do
168
+
169
+ spec "[!t55ce] collects Pathname objects when block argument is not passed." do
170
+ arr = ["A.txt", "B.txt", "C.txt"]
171
+ ok {arr.paths}.all? {|x| x.is_a?(Pathname) }
172
+ end
173
+
174
+ spec "[!yjkm5] yields Pathname objects when block argument is passed." do
175
+ arr = ["A.txt", "B.txt", "C.txt"]
176
+ ok {arr.paths{|x| x.exist?}} == [false, false, false]
177
+ end
178
+
179
+ spec "[!4kppy] self is Patname object in block argument." do
180
+ arr = ["A.txt", "B.txt", "C.txt"]
181
+ ok {arr.paths{self.is_a?(Pathname)}}.all? {|x| x == true }
182
+ end
183
+
184
+ end
185
+
186
+
187
+ fixture :dummy_files do
188
+ pr = proc do
189
+ if File.directory?("_test.d")
190
+ Dir.glob("_test.d/**/*").each {|x| File.unlink(x) if File.file?(x) }
191
+ Dir.glob("_test.d/**/*").sort.reverse.each {|x| Dir.rmdir(x) }
192
+ Dir.rmdir("_test.d")
193
+ end
194
+ end
195
+ pr.call
196
+ at_end(&pr)
197
+ Dir.mkdir "_test.d"
198
+ Dir.mkdir "_test.d/src"
199
+ Dir.mkdir "_test.d/lib"
200
+ File.open("_test.d/src/file1.txt", "w") {|f| f.write("file1") }
201
+ File.open("_test.d/src/file2.txt", "w") {|f| f.write("file2") }
202
+ nil
203
+ end
204
+
205
+ def _write_file(filepath, content)
206
+ File.open(filepath, "w") {|f| f.write(content) }
207
+ end
208
+
209
+
210
+ topic '#edit()' do
211
+
212
+ spec "[!ur9mj] opens file with utf-8 encoding." do
213
+ |dummy_files|
214
+ files = Dir.glob("_test.d/src/*.txt")
215
+ arr = []
216
+ files.edit {|s|
217
+ arr << s.encoding.name
218
+ s
219
+ }
220
+ ok {arr} == ["UTF-8", "UTF-8"]
221
+ end
222
+
223
+ spec "[!qqegl] file content and file path are passed to block argument." do
224
+ |dummy_files|
225
+ files = Dir.glob("_test.d/src/*.txt")
226
+ arr = []
227
+ files.edit {|s, fpath| arr << fpath }
228
+ ok {arr} == files
229
+ end
230
+
231
+ spec "[!d8dxv] make content as self in block argument." do
232
+ |dummy_files|
233
+ files = Dir.glob("_test.d/src/*.txt")
234
+ arr = []
235
+ files.edit {|s| arr << (s.eql? self); s}
236
+ ok {arr} == [true, true]
237
+ end
238
+
239
+ spec "[!9g7re] edit file when content changed." do
240
+ |dummy_files|
241
+ files = Dir.glob("_test.d/src/*.txt")
242
+ ret = files.edit {|s|
243
+ s << "-homhom\n"
244
+ s
245
+ }
246
+ ok {ret} == [
247
+ "Edit: '_test.d/src/file1.txt'",
248
+ "Edit: '_test.d/src/file2.txt'",
249
+ ]
250
+ ok {File.read("_test.d/src/file1.txt")} == "file1-homhom\n"
251
+ ok {File.read("_test.d/src/file2.txt")} == "file2-homhom\n"
252
+ end
253
+
254
+ spec "[!exzkz] don't edit file when content not changed." do
255
+ |dummy_files|
256
+ files = Dir.glob("_test.d/src/*.txt")
257
+ ret = files.edit {|s|
258
+ s
259
+ }
260
+ ok {ret} == [
261
+ "NotChanged: '_test.d/src/file1.txt'",
262
+ "NotChanged: '_test.d/src/file2.txt'",
263
+ ]
264
+ ok {File.read("_test.d/src/file1.txt")} == "file1"
265
+ ok {File.read("_test.d/src/file2.txt")} == "file2"
266
+ end
267
+
268
+ spec "[!k9d31] skips if file not exist." do
269
+ |dummy_files|
270
+ files = Dir.glob("_test.d/src/*.txt").map{|x| x.sub(/\.txt/, '.tmp')}
271
+ ret = files.edit {|s|
272
+ s << "hom\n"
273
+ }
274
+ ok {ret} == [
275
+ "Skip: '_test.d/src/file1.tmp' does not exist.",
276
+ "Skip: '_test.d/src/file2.tmp' does not exist.",
277
+ ]
278
+ ok {"_test.d/src/file1.tmp"}.NOT.exist?
279
+ ok {"_test.d/src/file2.tmp"}.NOT.exist?
280
+ end
281
+
282
+ spec "[!6m49n] skips if file is not a file." do
283
+ |dummy_files|
284
+ files = ["_test.d/src", "_test.d/lib"]
285
+ ret = files.edit {|s|
286
+ s << "hom\n"
287
+ }
288
+ ok {ret} == [
289
+ "Skip: '_test.d/src' is not a file.",
290
+ "Skip: '_test.d/lib' is not a file.",
291
+ ]
292
+ end
293
+
294
+ end
295
+
296
+
297
+ topic '#edit_i()' do
298
+
299
+ spec "[!lpncu] creates backup file with suffix spedified." do
300
+ |dummy_files|
301
+ files = Dir.glob("_test.d/src/*.txt")
302
+ ret = files.edit_i(".bkup") {|s|
303
+ s << "hom\n"
304
+ }
305
+ ok {ret} == [
306
+ "Edit: '_test.d/src/file1.txt'",
307
+ "Edit: '_test.d/src/file2.txt'",
308
+ ]
309
+ ok {"_test.d/src/file1.txt"}.file_exist?
310
+ ok {"_test.d/src/file2.txt"}.file_exist?
311
+ ok {"_test.d/src/file1.txt.bkup"}.file_exist?
312
+ ok {"_test.d/src/file2.txt.bkup"}.file_exist?
313
+ end
314
+
315
+ end
316
+
317
+
318
+ topic '#move_to()' do
319
+
320
+ spec "[!n0ubo] block argument is required." do
321
+ pr = proc { ["file1"].move_to }
322
+ ok {pr}.raise?(ArgumentError, "move_to(): block argument required.")
323
+ end
324
+
325
+ spec "[!qqzqz] trims target file name." do
326
+ |dummy_files|
327
+ arr = [" _test.d/src/file1.txt\n", " _test.d/src/file2.txt\n"]
328
+ arr.move_to {"_test.d/lib"}
329
+ ok {"_test.d/lib/file1.txt"}.file_exist?
330
+ ok {"_test.d/lib/file2.txt"}.file_exist?
331
+ end
332
+
333
+ spec "[!nnud9] destination directory name is derived from target file name." do
334
+ |dummy_files|
335
+ Dir.mkdir("_test.d/lib1")
336
+ Dir.mkdir("_test.d/lib2")
337
+ Dir.glob("_test.d/src/*.txt").move_to {|s| s =~ /file(\d+)\.\w+$/; "_test.d/lib#{$1}" }
338
+ ok {"_test.d/lib/file1.txt"}.NOT.exist?
339
+ ok {"_test.d/lib/file2.txt"}.NOT.exist?
340
+ ok {"_test.d/lib1/file1.txt"}.file_exist?
341
+ ok {"_test.d/lib2/file2.txt"}.file_exist?
342
+ end
343
+
344
+ spec "[!n7a1q] prints target file and destination directory when verbose mode." do
345
+ |dummy_files|
346
+ ret = Dir.glob("_test.d/src/*.txt").move_to {"_test.d/lib"}
347
+ ok {ret} == [
348
+ "Move: '_test.d/src/file1.txt' => '_test.d/lib'",
349
+ "Move: '_test.d/src/file2.txt' => '_test.d/lib'",
350
+ ]
351
+ end
352
+
353
+ spec "[!ey3e4] if target directory name is nil or empty, skip moving file." do
354
+ |dummy_files|
355
+ expected = [
356
+ "Skip: target directory name is nil or empty (file: '_test.d/src/file1.txt')",
357
+ "Skip: target directory name is nil or empty (file: '_test.d/src/file2.txt')",
358
+ ]
359
+ ret = Dir.glob("_test.d/src/*.txt").move_to {""}
360
+ ok {ret} == expected
361
+ ret = Dir.glob("_test.d/src/*.txt").move_to {nil}
362
+ ok {ret} == expected
363
+ end
364
+
365
+ spec "[!i5jt6] if destination directory exists, move file to it." do
366
+ |dummy_files|
367
+ ret = Dir.glob("_test.d/src/*.txt").move_to {"_test.d/lib"}
368
+ ok {"_test.d/lib/file1.txt"}.file_exist?
369
+ ok {"_test.d/lib/file2.txt"}.file_exist?
370
+ end
371
+
372
+ spec "[!azqgk] if there is a file that name is same as desination directory, skip." do
373
+ |dummy_files|
374
+ Dir.rmdir("_test.d/lib")
375
+ File.open("_test.d/lib", "w") {|f| f.write("x") }
376
+ ret = Dir.glob("_test.d/src/*.txt").move_to {"_test.d/lib"}
377
+ ok {ret} == [
378
+ "Skip: directory '_test.d/lib' not a directory",
379
+ "Skip: directory '_test.d/lib' not a directory",
380
+ ]
381
+ end
382
+
383
+ spec "[!rqu5q] if destinatio directory doesn't exist, skip." do
384
+ |dummy_files|
385
+ Dir.rmdir("_test.d/lib")
386
+ ret = Dir.glob("_test.d/src/*.txt").move_to {"_test.d/lib"}
387
+ ok {ret} == [
388
+ "Skip: directory '_test.d/lib' not exist",
389
+ "Skip: directory '_test.d/lib' not exist",
390
+ ]
391
+ end
392
+
393
+ spec "[!0gq9h] if destination file already exist, skip." do
394
+ |dummy_files|
395
+ _write_file("_test.d/lib/file1.txt", "xxx")
396
+ _write_file("_test.d/lib/file2.txt", "yyy")
397
+ ret = Dir.glob("_test.d/src/*.txt").move_to {"_test.d/lib"}
398
+ ok {ret} == [
399
+ "Skip: destination file '_test.d/lib/file1.txt' already exist.",
400
+ "Skip: destination file '_test.d/lib/file2.txt' already exist.",
401
+ ]
402
+ ok {File.read("_test.d/lib/file1.txt")} == "xxx" # not overwritten
403
+ ok {File.read("_test.d/lib/file2.txt")} == "yyy" # not overwrirten
404
+ end
405
+
406
+ end
407
+
408
+
409
+ topic '#move_to!()' do
410
+
411
+ spec "[!40se5] block argument is required." do
412
+ pr = proc { ["file1"].move_to! }
413
+ ok {pr}.raise?(ArgumentError, "move_to!(): block argument required.")
414
+ end
415
+
416
+ spec "[!ebdqh] overwrite destination file even if it exists." do
417
+ |dummy_files|
418
+ _write_file("_test.d/lib/file1.txt", "xxx")
419
+ _write_file("_test.d/lib/file2.txt", "yyy")
420
+ ret = Dir.glob("_test.d/src/*.txt").move_to! {"_test.d/lib"}
421
+ ok {ret} == [
422
+ "Move!: '_test.d/src/file1.txt' => '_test.d/lib'",
423
+ "Move!: '_test.d/src/file2.txt' => '_test.d/lib'",
424
+ ]
425
+ ok {File.read("_test.d/lib/file1.txt")} == "file1" # overwritten
426
+ ok {File.read("_test.d/lib/file2.txt")} == "file2" # overwrirten
427
+ end
428
+
429
+ spec "[!itsh0] use 'Move!' instead of 'Move' when overwriting existing file." do
430
+ |dummy_files|
431
+ _write_file("_test.d/lib/file1.txt", "xxx")
432
+ _write_file("_test.d/lib/file2.txt", "yyy")
433
+ ret = Dir.glob("_test.d/src/*.txt").move_to! {"_test.d/lib"}
434
+ ok {ret} == [
435
+ "Move!: '_test.d/src/file1.txt' => '_test.d/lib'",
436
+ "Move!: '_test.d/src/file2.txt' => '_test.d/lib'",
437
+ ]
438
+ end
439
+
440
+ end
441
+
442
+
443
+ topic '#mkdir_and_move_to()' do
444
+
445
+ spec "[!k74dw] block argument is required." do
446
+ pr = proc { ["file1"].mkdir_and_move_to }
447
+ ok {pr}.raise?(ArgumentError, "mkdir_and_move_to(): block argument required.")
448
+ end
449
+
450
+ spec "[!b9d4m] if destination directory doesn't exist, creates it." do
451
+ |dummy_files|
452
+ files = Dir.glob("_test.d/src/*.txt")
453
+ ret = files.mkdir_and_move_to {|s| s =~ /file(\d+)/; "_test.d/lib#{$1}" }
454
+ ok {"_test.d/lib1/file1.txt"}.file_exist?
455
+ ok {"_test.d/lib2/file2.txt"}.file_exist?
456
+ ok {ret} == [
457
+ "Move: '_test.d/src/file1.txt' => '_test.d/lib1'",
458
+ "Move: '_test.d/src/file2.txt' => '_test.d/lib2'",
459
+ ]
460
+ end
461
+
462
+ end
463
+
464
+
465
+ topic '#mkdir_and_move_to!()' do
466
+
467
+ spec "[!z9yus] block argument is required." do
468
+ pr = proc { ["file1"].mkdir_and_move_to! }
469
+ ok {pr}.raise?(ArgumentError, "mkdir_and_move_to!(): block argument required.")
470
+ end
471
+
472
+ end
473
+
474
+
475
+ topic '#copy_to()' do
476
+
477
+ spec "[!fa5y0] copy files or directories into destination directory." do
478
+ |dummy_files|
479
+ files = Dir.glob("_test.d/src/*.txt")
480
+ ret = files.copy_to { "_test.d/lib" }
481
+ ok {ret} == [
482
+ "Copy: '_test.d/src/file1.txt' => '_test.d/lib'",
483
+ "Copy: '_test.d/src/file2.txt' => '_test.d/lib'",
484
+ ]
485
+ ok {"_test.d/src/file1.txt"}.file_exist?
486
+ ok {"_test.d/src/file2.txt"}.file_exist?
487
+ ok {"_test.d/lib/file1.txt"}.file_exist?
488
+ ok {"_test.d/lib/file2.txt"}.file_exist?
489
+ end
490
+
491
+ end
492
+
493
+
494
+ topic '#copy_to!()' do
495
+
496
+ end
497
+
498
+
499
+ topic '#mkdir_and_copy_to()' do
500
+
501
+ end
502
+
503
+
504
+ topic '#mkdir_and_copy_to!()' do
505
+
506
+ end
507
+
508
+
509
+ topic '#rename_as()' do
510
+
511
+ spec "[!ignfm] block argument is required." do
512
+ |dummy_files|
513
+ files = Dir.glob("_test.d/src/*.txt")
514
+ pr = proc {files.rename_as("_test.d/lib/file.txt")}
515
+ ok {pr}.raise?(ArgumentError, "rename_as(): block argument required.")
516
+ end
517
+
518
+ spec "[!qqzqz] trims target file name." do
519
+ |dummy_files|
520
+ files = Dir.glob("_test.d/src/*.txt").map {|s| " #{s}\n"}
521
+ files.rename_as{sub(/src/, 'lib')}
522
+ ok {"_test.d/src/file1.txt"}.NOT.exist?
523
+ ok {"_test.d/src/file2.txt"}.NOT.exist?
524
+ ok {"_test.d/lib/file1.txt"}.file_exist?
525
+ ok {"_test.d/lib/file2.txt"}.file_exist?
526
+ end
527
+
528
+ spec "[!nnud9] destination file name is derived from source file name." do
529
+ |dummy_files|
530
+ files = Dir.glob("_test.d/src/*.txt")
531
+ files.rename_as{sub(/\.txt$/, '.tmp')}
532
+ ok {"_test.d/src/file1.txt"}.NOT.exist?
533
+ ok {"_test.d/src/file2.txt"}.NOT.exist?
534
+ ok {"_test.d/src/file1.tmp"}.file_exist?
535
+ ok {"_test.d/src/file2.tmp"}.file_exist?
536
+ end
537
+
538
+ spec "[!dkejf] if target directory name is nil or empty, skips renaming file." do
539
+ |dummy_files|
540
+ files = Dir.glob("_test.d/src/*.txt")
541
+ ret = files.rename_as{nil}
542
+ ok {ret} == [
543
+ "Skip: target file name is nil or empty (file: '_test.d/src/file1.txt')",
544
+ "Skip: target file name is nil or empty (file: '_test.d/src/file2.txt')",
545
+ ]
546
+ ok {"_test.d/src/file1.txt"}.file_exist?
547
+ ok {"_test.d/src/file2.txt"}.file_exist?
548
+ #
549
+ ret = files.rename_as{""}
550
+ ok {ret} == [
551
+ "Skip: target file name is nil or empty (file: '_test.d/src/file1.txt')",
552
+ "Skip: target file name is nil or empty (file: '_test.d/src/file2.txt')",
553
+ ]
554
+ ok {"_test.d/src/file1.txt"}.file_exist?
555
+ ok {"_test.d/src/file2.txt"}.file_exist?
556
+ end
557
+
558
+ spec "[!8ap57] if target file or directory already exists, skips renaming files." do
559
+ |dummy_files|
560
+ files = Dir.glob("_test.d/src/*.txt")
561
+ _write_file("_test.d/lib/file1.txt", "xxx")
562
+ _write_file("_test.d/lib/file2.txt", "yyy")
563
+ ret = files.rename_as {sub(/src/, 'lib')}
564
+ ok {ret} == [
565
+ "Skip: target file '_test.d/lib/file1.txt' already exists.",
566
+ "Skip: target file '_test.d/lib/file2.txt' already exists.",
567
+ ]
568
+ ok {"_test.d/src/file1.txt"}.file_exist?
569
+ ok {"_test.d/src/file2.txt"}.file_exist?
570
+ ok {"_test.d/lib/file1.txt"}.file_exist?
571
+ ok {"_test.d/lib/file2.txt"}.file_exist?
572
+ end
573
+
574
+ spec "[!qhlc8] if directory of target file already exists, renames file." do
575
+ |dummy_files|
576
+ files = Dir.glob("_test.d/src/*.txt")
577
+ ret = files.rename_as {sub(/src/, 'lib').sub(/\.txt/, '.tmp')}
578
+ ok {ret} == [
579
+ "Rename: '_test.d/src/file1.txt' => '_test.d/lib/file1.tmp'",
580
+ "Rename: '_test.d/src/file2.txt' => '_test.d/lib/file2.tmp'",
581
+ ]
582
+ ok {"_test.d/src/file1.txt"}.NOT.exist?
583
+ ok {"_test.d/src/file2.txt"}.NOT.exist?
584
+ ok {"_test.d/lib/file1.tmp"}.file_exist?
585
+ ok {"_test.d/lib/file2.tmp"}.file_exist?
586
+ end
587
+
588
+ spec "[!gg9w1] if directory of target file not exist, skips renaming files." do
589
+ |dummy_files|
590
+ files = Dir.glob("_test.d/src/*.txt")
591
+ ret = files.rename_as {sub(/src/, 'var')}
592
+ ok {ret} == [
593
+ "Skip: directory of target file '_test.d/var/file1.txt' not exist.",
594
+ "Skip: directory of target file '_test.d/var/file2.txt' not exist.",
595
+ ]
596
+ ok {"_test.d/src/file1.txt"}.file_exist?
597
+ ok {"_test.d/src/file2.txt"}.file_exist?
598
+ ok {"_test.d/var/file1.txt"}.NOT.exist?
599
+ ok {"_test.d/var/file2.txt"}.NOT.exist?
600
+ end
601
+
602
+ spec "[!vt24y] prints target file and destination directory when verbose mode." do
603
+ |dummy_files|
604
+ files = Dir.glob("_test.d/src/*.txt")
605
+ ret = files.rename_as {sub(/src/, 'lib').sub(/.txt/, '.tmp')}
606
+ ok {ret} == [
607
+ "Rename: '_test.d/src/file1.txt' => '_test.d/lib/file1.tmp'",
608
+ "Rename: '_test.d/src/file2.txt' => '_test.d/lib/file2.tmp'",
609
+ ]
610
+ end
611
+
612
+ end
613
+
614
+
615
+ topic '#rename_as!()' do
616
+
617
+ spec "[!ignfm] block argument is required." do
618
+ |dummy_files|
619
+ files = Dir.glob("_test.d/src/*.txt")
620
+ pr = proc {files.rename_as!("_test.d/lib/file.txt")}
621
+ ok {pr}.raise?(ArgumentError, "rename_as!(): block argument required.")
622
+ end
623
+
624
+ spec "[!qqzqz] trims target file name." do
625
+ skip_when true, "(common to rename_as())"
626
+ end
627
+
628
+ spec "[!nnud9] destination file name is derived from source file name." do
629
+ skip_when true, "(common to rename_as())"
630
+ end
631
+
632
+ spec "[!dkejf] if target directory name is nil or empty, skips renaming file." do
633
+ skip_when true, "(common to rename_as())"
634
+ end
635
+
636
+ spec "[!1yzjd] if target file or directory already exists, removes it before renaming file." do
637
+ |dummy_files|
638
+ files = Dir.glob("_test.d/src/*.txt")
639
+ _write_file("_test.d/lib/file1.txt", "xxx")
640
+ _write_file("_test.d/lib/file2.txt", "yyy")
641
+ ret = files.rename_as! {sub(/src/, 'lib')}
642
+ ok {ret} == [
643
+ "Rename!: '_test.d/src/file1.txt' => '_test.d/lib/file1.txt'",
644
+ "Rename!: '_test.d/src/file2.txt' => '_test.d/lib/file2.txt'",
645
+ ]
646
+ ok {"_test.d/src/file1.txt"}.NOT.exist?
647
+ ok {"_test.d/src/file2.txt"}.NOT.exist?
648
+ ok {"_test.d/lib/file1.txt"}.file_exist?
649
+ ok {"_test.d/lib/file2.txt"}.file_exist?
650
+ end
651
+
652
+ spec "[!qhlc8] if directory of target file already exists, renames file." do
653
+ skip_when true, "(common to rename_as())"
654
+ end
655
+
656
+ spec "[!gg9w1] if directory of target file not exist, skips renaming files." do
657
+ skip_when true, "(common to rename_as())"
658
+ end
659
+
660
+ spec "[!vt24y] prints target file and destination directory when verbose mode." do
661
+ skip_when true, "(common to rename_as())"
662
+ end
663
+
664
+ spec "[!gd9j9] use 'Rename!' instead of 'Rename' when overwriting existing file." do
665
+ |dummy_files|
666
+ files = Dir.glob("_test.d/src/*.txt")
667
+ _write_file("_test.d/lib/file1.txt", "xxx")
668
+ _write_file("_test.d/lib/file2.txt", "yyy")
669
+ ret = files.rename_as! {sub(/src/, 'lib')}
670
+ ok {ret} == [
671
+ "Rename!: '_test.d/src/file1.txt' => '_test.d/lib/file1.txt'",
672
+ "Rename!: '_test.d/src/file2.txt' => '_test.d/lib/file2.txt'",
673
+ ]
674
+ end
675
+
676
+ end
677
+
678
+
679
+ topic '#mkdir_and_rename_as()' do
680
+
681
+ spec "[!ignfm] block argument is required." do
682
+ |dummy_files|
683
+ files = Dir.glob("_test.d/src/*.txt")
684
+ pr = proc {files.mkdir_and_rename_as("_test.d/lib/file.txt")}
685
+ ok {pr}.raise?(ArgumentError, "mkdir_and_rename_as(): block argument required.")
686
+ end
687
+
688
+ spec "[!qqzqz] trims target file name." do
689
+ skip_when true, "(common to rename_as())"
690
+ end
691
+
692
+ spec "[!nnud9] destination file name is derived from source file name." do
693
+ skip_when true, "(common to rename_as())"
694
+ end
695
+
696
+ spec "[!dkejf] if target directory name is nil or empty, skips renaming file." do
697
+ skip_when true, "(common to rename_as())"
698
+ end
699
+
700
+ spec "[!8ap57] if target file or directory already exists, skips renaming files." do
701
+ skip_when true, "(common to rename_as())"
702
+ end
703
+
704
+ spec "[!qhlc8] if directory of target file already exists, renames file." do
705
+ skip_when true, "(common to rename_as())"
706
+ end
707
+
708
+ spec "[!sh2ti] if directory of target file not exist, creates it." do
709
+ |dummy_files|
710
+ files = Dir.glob("_test.d/src/*.txt")
711
+ ret = files.mkdir_and_rename_as {sub(/src/, 'var/tmp').sub(/\.txt/, '.tmp')}
712
+ ok {ret} == [
713
+ "Rename: '_test.d/src/file1.txt' => '_test.d/var/tmp/file1.tmp'",
714
+ "Rename: '_test.d/src/file2.txt' => '_test.d/var/tmp/file2.tmp'",
715
+ ]
716
+ ok {"_test.d/src/file1.txt"}.NOT.exist?
717
+ ok {"_test.d/src/file2.txt"}.NOT.exist?
718
+ ok {"_test.d/var/tmp/file1.tmp"}.file_exist?
719
+ ok {"_test.d/var/tmp/file2.tmp"}.file_exist?
720
+ end
721
+
722
+ spec "[!vt24y] prints source and destination file path when verbose mode." do
723
+ skip_when true, "(common to rename_as())"
724
+ end
725
+
726
+ end
727
+
728
+
729
+ topic '#mkdir_and_rename_as!()' do
730
+
731
+ spec "[!ignfm] block argument is required." do
732
+ |dummy_files|
733
+ files = Dir.glob("_test.d/src/*.txt")
734
+ pr = proc {files.mkdir_and_rename_as!("_test.d/lib/file.txt")}
735
+ ok {pr}.raise?(ArgumentError, "mkdir_and_rename_as!(): block argument required.")
736
+ end
737
+
738
+ spec "[!qqzqz] trims target file name." do
739
+ skip_when true, "(common to rename_as())"
740
+ end
741
+
742
+ spec "[!nnud9] destination file name is derived from source file name." do
743
+ skip_when true, "(common to rename_as())"
744
+ end
745
+
746
+ spec "[!dkejf] if target directory name is nil or empty, skips renaming file." do
747
+ skip_when true, "(common to rename_as())"
748
+ end
749
+
750
+ spec "[!1yzjd] if target file or directory already exists, removes it before renaming file." do
751
+ skip_when true, "(common to rename_as!())"
752
+ end
753
+
754
+ spec "[!qhlc8] if directory of target file already exists, renames file." do
755
+ skip_when true, "(common to rename_as())"
756
+ end
757
+
758
+ spec "[!sh2ti] if directory of target file not exist, creates it." do
759
+ skip_when true, "(common to mkdir_and_rename_as())"
760
+ end
761
+
762
+ spec "[!vt24y] prints source and destination file path when verbose mode." do
763
+ skip_when true, "(common to rename_as())"
764
+ end
765
+
766
+ end
767
+
768
+
769
+ topic '#copy_as()' do
770
+
771
+ spec "[!0txp4] copy files or directories." do
772
+ |dummy_files|
773
+ files = Dir.glob("_test.d/src/*.txt")
774
+ ret = files.copy_as { sub(/src/, 'lib').sub(/\.txt$/, '.tmp') }
775
+ ok {ret} == [
776
+ "Copy: '_test.d/src/file1.txt' => '_test.d/lib/file1.tmp'",
777
+ "Copy: '_test.d/src/file2.txt' => '_test.d/lib/file2.tmp'",
778
+ ]
779
+ ok {"_test.d/src/file1.txt"}.file_exist?
780
+ ok {"_test.d/src/file2.txt"}.file_exist?
781
+ ok {"_test.d/lib/file1.tmp"}.file_exist?
782
+ ok {"_test.d/lib/file2.tmp"}.file_exist?
783
+ end
784
+
785
+ end
786
+
787
+
788
+ topic '#copy_as!()' do
789
+
790
+ end
791
+
792
+
793
+ topic '#mkdir_and_copy_as()' do
794
+
795
+ end
796
+
797
+
798
+ topic '#mkdir_and_copy_as!()' do
799
+
800
+ end
801
+
802
+
803
+ end
804
+
805
+
806
+ topic Enumerator::Lazy do
807
+
808
+
809
+ topic '#map()' do
810
+
811
+ spec "[!drgky] each item is available as self in block of map()." do
812
+ ok { (1..3).lazy.map {|i| i * 10 } }.is_a?(Enumerator::Lazy)
813
+ ok { (1..3).lazy.map {|i| i * 10 }.to_a } == [10, 20, 30]
814
+ ok { (1..3).lazy.map {|i| self*10}.to_a } == [10, 20, 30]
815
+ end
816
+
817
+ end
818
+
819
+
820
+ topic '#select()' do
821
+
822
+ spec "[!uhqz2] each item is available as self in block of map()." do
823
+ ok { (1..5).lazy.select {|i| i % 2 == 0 } }.is_a?(Enumerator::Lazy)
824
+ ok { (1..5).lazy.select {|i| i % 2 == 0 }.to_a } == [2, 4]
825
+ ok { (1..5).lazy.select {|i| self % 2 == 0 }.to_a } == [2, 4]
826
+ end
827
+
828
+ end
829
+
830
+
831
+ end
832
+
833
+
834
+ end