external 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/History +5 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +168 -0
  4. data/lib/ext_arc.rb +108 -0
  5. data/lib/ext_arr.rb +727 -0
  6. data/lib/ext_ind.rb +1120 -0
  7. data/lib/external/base.rb +85 -0
  8. data/lib/external/chunkable.rb +105 -0
  9. data/lib/external/enumerable.rb +137 -0
  10. data/lib/external/io.rb +398 -0
  11. data/lib/external.rb +3 -0
  12. data/test/benchmarks/benchmarks_20070918.txt +45 -0
  13. data/test/benchmarks/benchmarks_20070921.txt +91 -0
  14. data/test/benchmarks/benchmarks_20071006.txt +147 -0
  15. data/test/benchmarks/test_copy_file.rb +80 -0
  16. data/test/benchmarks/test_pos_speed.rb +47 -0
  17. data/test/benchmarks/test_read_time.rb +55 -0
  18. data/test/cached_ext_ind_test.rb +219 -0
  19. data/test/check/benchmark_check.rb +441 -0
  20. data/test/check/namespace_conflicts_check.rb +23 -0
  21. data/test/check/pack_check.rb +90 -0
  22. data/test/ext_arc_test.rb +286 -0
  23. data/test/ext_arr/alt_sep.txt +3 -0
  24. data/test/ext_arr/cr_lf_input.txt +3 -0
  25. data/test/ext_arr/input.index +0 -0
  26. data/test/ext_arr/input.txt +1 -0
  27. data/test/ext_arr/inputb.index +0 -0
  28. data/test/ext_arr/inputb.txt +1 -0
  29. data/test/ext_arr/lf_input.txt +3 -0
  30. data/test/ext_arr/lines.txt +19 -0
  31. data/test/ext_arr/without_index.txt +1 -0
  32. data/test/ext_arr_test.rb +534 -0
  33. data/test/ext_ind_test.rb +1472 -0
  34. data/test/external/base_test.rb +74 -0
  35. data/test/external/chunkable_test.rb +182 -0
  36. data/test/external/index/input.index +0 -0
  37. data/test/external/index/inputb.index +0 -0
  38. data/test/external/io_test.rb +414 -0
  39. data/test/external_test_helper.rb +31 -0
  40. data/test/external_test_suite.rb +4 -0
  41. data/test/test_array.rb +1192 -0
  42. metadata +104 -0
@@ -0,0 +1,534 @@
1
+ require File.join(File.dirname(__FILE__), 'external_test_helper.rb')
2
+ require 'ext_arr'
3
+ require 'fileutils'
4
+
5
+ class ExtArrTest < Test::Unit::TestCase
6
+ include Benchmark
7
+ include TestArray
8
+
9
+ attr_reader :ea, :tempfile
10
+
11
+ def setup
12
+ # cls represents an array
13
+ @cls = ExtArr
14
+
15
+ @tempfile = Tempfile.new("eatest")
16
+ @tempfile << string
17
+ @tempfile.pos = 0
18
+
19
+ @ea = ExtArr.new(@tempfile)
20
+ @ea.index.concat(index)
21
+ end
22
+
23
+ def teardown
24
+ @tempfile.close unless @tempfile.closed?
25
+ end
26
+
27
+ def string
28
+ "abcdefgh"
29
+ end
30
+
31
+ def array
32
+ ["abc", "de", "fgh"]
33
+ end
34
+
35
+ def index
36
+ [[0,3],[3,2],[5,3]]
37
+ end
38
+
39
+ def filepath(path)
40
+ File.join(File.dirname(__FILE__), "ext_arr", path)
41
+ end
42
+
43
+ #
44
+ # doc tests
45
+ #
46
+
47
+ def test_readme_doc_for_ext_arr
48
+ ea = ExtArr[1, 2.2, "cat", {:key => 'value'}]
49
+ assert_equal "cat", ea[2]
50
+ assert_equal({:key => 'value'}, ea.last)
51
+ ea << [:a, :b]
52
+ assert_equal [1, 2.2, "cat", {:key => 'value'}, [:a, :b]], ea.to_a
53
+
54
+ assert_equal Tempfile, ea.io.class
55
+ ea.io.rewind
56
+ assert_equal "--- 1\n--- 2.2\n--- cat\n--- \n:key: value\n--- \n- :a\n- :b\n", ea.io.read
57
+
58
+ assert_equal ExtInd, ea.index.class
59
+ assert_equal [[0, 6], [6, 8], [14, 8], [22, 17], [39, 15]], ea.index.to_a
60
+
61
+ Tempfile.open("test_readme_doc_for_ext_arr") do |file|
62
+ file << "--- 1\n--- 2.2\n--- cat\n--- \n:key: value\n--- \n- :a\n- :b\n"
63
+ file.flush
64
+
65
+ index_filepath = ExtArr.default_index_filepath(file.path)
66
+ assert !File.exists?(index_filepath)
67
+
68
+ ea = ExtArr.new(file)
69
+ assert_equal [], ea.to_a
70
+ ea.reindex
71
+ assert_equal [1, 2.2, "cat", {:key => 'value'}, [:a, :b]], ea.to_a
72
+ end
73
+ end
74
+
75
+ #
76
+ # test setup
77
+ #
78
+
79
+ def test_setup
80
+ assert_equal ExtArr, @cls
81
+
82
+ assert_equal string, tempfile.read
83
+ assert_equal tempfile.path, ea.io.path
84
+ assert_equal index, ea.index.to_a
85
+ end
86
+
87
+ #
88
+ # initialize tests
89
+ #
90
+
91
+ def test_initialize
92
+ ea = ExtArr.new
93
+
94
+ assert_equal Tempfile, ea.io.class
95
+ assert_equal "", ea.io.read
96
+
97
+ assert ea.index.cached?
98
+ assert_equal [], ea.index.to_a
99
+ end
100
+
101
+ def test_initialize_with_existing_file_and_index
102
+ File.open(filepath("input.txt")) do |file|
103
+ ea = ExtArr.new(file)
104
+
105
+ assert_equal 'input.txt', File.basename(ea.io.path)
106
+ assert_equal string, ea.io.read
107
+ assert_equal index, ea.index.to_a
108
+
109
+ ea.close
110
+ end
111
+ end
112
+
113
+ def test_initialize_load_specified_index_file
114
+ File.open(filepath('without_index.txt')) do |file|
115
+ alt_index = filepath('input.index')
116
+
117
+ assert File.exists?(alt_index)
118
+
119
+ ea = ExtArr.new(file, :index_file => alt_index)
120
+ assert_equal File.read(alt_index).unpack("I*"), ea.index.to_a.flatten
121
+ ea.close
122
+ end
123
+ end
124
+
125
+ def test_initialize_in_uncached_mode_uses_external_index
126
+ ea = ExtArr.new(nil, :cached => false)
127
+
128
+ assert_equal Tempfile, ea.io.class
129
+ assert_equal "", ea.io.read
130
+
131
+ assert_equal ExtInd, ea.index.class
132
+ assert_equal [], ea.index.read
133
+ end
134
+
135
+ def test_initialize_with_existing_file_and_non_existant_index_file_creates_index_file_in_uncached_mode
136
+ File.open(filepath('without_index.txt')) do |file|
137
+ index_file = filepath('without_index.index')
138
+ begin
139
+ assert !File.exists?(index_file)
140
+ ea = ExtArr.new(file, :cached => false)
141
+
142
+ assert_equal ExtInd, ea.index.class
143
+ assert File.exists?(ea.index.io.path)
144
+
145
+ ea.close
146
+ ensure
147
+ FileUtils.rm(index_file) if File.exists?(index_file)
148
+ end
149
+ end
150
+ end
151
+
152
+ #
153
+ # test reindex
154
+ #
155
+
156
+ def test_reindex
157
+ arr = [1, 2, 3.3, "cat", {:key => 'value'}]
158
+ StringIO.open("--- 1\n--- 2\n--- 3.3\n--- cat\n--- \n:key: value\n") do |strio|
159
+ ea = ExtArr.new(strio)
160
+ ea.reindex
161
+
162
+ assert_equal [[0, 6], [6, 6], [12, 8], [20, 8], [28, 17]], ea.index.to_a
163
+ assert_equal arr, ea.to_a
164
+ end
165
+ end
166
+
167
+ # def test_reindex_yaml_strings
168
+ # arr = [[1,2,3].to_yaml]
169
+ # StringIO.open(arr.to_yaml) do |strio|
170
+ # ea = ExtArr.new(strio)
171
+ # ea.reindex
172
+ # assert_equal arr, ea.to_a
173
+ # end
174
+ # end
175
+
176
+
177
+ #
178
+ # test close
179
+ #
180
+
181
+ def test_close_multiple_times_does_not_raise_error
182
+ ea.close
183
+ ea.close
184
+ end
185
+
186
+ def test_close_closed_index_if_uncached
187
+ ea = ExtArr.new(nil, :cached => false)
188
+ assert !ea.index.closed?
189
+ assert !ea.closed?
190
+
191
+ ea.close
192
+
193
+ assert ea.index.closed?
194
+ assert ea.closed?
195
+ end
196
+
197
+ #
198
+ # entry_to_str, str_to_entry test
199
+ #
200
+
201
+ def test_entry_to_str_and_str_to_entry_are_inverse_functions_for_objects_responding_to_to_yaml
202
+ [
203
+ nil, true, false,
204
+ :a, :symbol,
205
+ '', 'a', "abcde fghij", "1234", "with\nnewline", " \r \n \t ", " ", "\t", [1,2,3].to_yaml,
206
+ 0, 1, -1, 1.1, 18446744073709551615,
207
+ [], [1,2,3],
208
+ {}, {:key => 'value', 'another' => 1},
209
+ Time.now
210
+ ].each do |obj|
211
+ str = ea.entry_to_str(obj)
212
+ assert_equal obj, ea.str_to_entry(str)
213
+ end
214
+
215
+ # FLUNK CASES!
216
+ ["\r", "\n", "\r\n", "string_with_\r\n_internal"].each do |obj|
217
+ str = ea.entry_to_str(obj)
218
+ assert_not_equal obj, ea.str_to_entry(str)
219
+ end
220
+ end
221
+
222
+ def test_strings_and_numerics_can_be_converted_from_their_to_s
223
+ ['a', "abcde fghij"].each do |obj|
224
+ assert obj.kind_of?(String)
225
+ assert_equal obj, ea.str_to_entry(obj.to_s)
226
+ end
227
+
228
+ [1, -1, 1.1, 18446744073709551615].each do |obj|
229
+ assert obj.kind_of?(Numeric)
230
+ assert_equal obj, ea.str_to_entry(obj.to_s)
231
+ end
232
+ end
233
+
234
+ #############################
235
+ # Modified Array methods tests
236
+ #############################
237
+
238
+ def test_LSHIFT # '<<'
239
+ a = @cls[]
240
+ a << 1
241
+ assert_equal(@cls[1], a)
242
+ a << 2 << 3
243
+ assert_equal(@cls[1, 2, 3], a)
244
+ a << nil << 'cat'
245
+ assert_equal(@cls[1, 2, 3, nil, 'cat'], a)
246
+
247
+ # Changes: when you add a to itself, the version at
248
+ # the << line is added, not the one that appears in the
249
+ # comparison
250
+ #a << a
251
+ #assert_equal(@cls[1, 2, 3, nil, 'cat', a], a)
252
+
253
+ b = @cls.new
254
+ a << b
255
+ assert_equal(@cls[1, 2, 3, nil, 'cat', b], a)
256
+ end
257
+
258
+ def test_ASET # '[]='
259
+ a = @cls[*(0..99).to_a]
260
+ assert_equal(0, a[0] = 0)
261
+ assert_equal(@cls[0] + @cls[*(1..99).to_a], a)
262
+
263
+ a = @cls[*(0..99).to_a]
264
+ assert_equal(0, a[10,10] = 0)
265
+ assert_equal(@cls[*(0..9).to_a] + @cls[0] + @cls[*(20..99).to_a], a)
266
+
267
+ a = @cls[*(0..99).to_a]
268
+ assert_equal(0, a[-1] = 0)
269
+ assert_equal(@cls[*(0..98).to_a] + @cls[0], a)
270
+
271
+ a = @cls[*(0..99).to_a]
272
+ assert_equal(0, a[-10, 10] = 0)
273
+ assert_equal(@cls[*(0..89).to_a] + @cls[0], a)
274
+
275
+ a = @cls[*(0..99).to_a]
276
+ assert_equal(0, a[0,1000] = 0)
277
+ assert_equal(@cls[0] , a)
278
+
279
+ a = @cls[*(0..99).to_a]
280
+ assert_equal(0, a[10..19] = 0)
281
+ assert_equal(@cls[*(0..9).to_a] + @cls[0] + @cls[*(20..99).to_a], a)
282
+
283
+ b = @cls[*%w( a b c )]
284
+ a = @cls[*(0..99).to_a]
285
+ assert_equal(b, a[0,1] = b)
286
+ assert_equal(b + @cls[*(1..99).to_a], a)
287
+
288
+ a = @cls[*(0..99).to_a]
289
+ assert_equal(b, a[10,10] = b)
290
+ assert_equal(@cls[*(0..9).to_a] + b + @cls[*(20..99).to_a], a)
291
+
292
+ a = @cls[*(0..99).to_a]
293
+ assert_equal(b, a[-1, 1] = b)
294
+ assert_equal(@cls[*(0..98).to_a] + b, a)
295
+
296
+ a = @cls[*(0..99).to_a]
297
+ assert_equal(b, a[-10, 10] = b)
298
+ assert_equal(@cls[*(0..89).to_a] + b, a)
299
+
300
+ a = @cls[*(0..99).to_a]
301
+ assert_equal(b, a[0,1000] = b)
302
+ assert_equal(b , a)
303
+
304
+ a = @cls[*(0..99).to_a]
305
+ assert_equal(b, a[10..19] = b)
306
+ assert_equal(@cls[*(0..9).to_a] + b + @cls[*(20..99).to_a], a)
307
+
308
+ # Ruby 1.8 feature change:
309
+ # assigning nil does not remove elements.
310
+ =begin
311
+ a = @cls[*(0..99).to_a]
312
+ assert_equal(nil, a[0,1] = nil)
313
+ assert_equal(@cls[*(1..99).to_a], a)
314
+
315
+ a = @cls[*(0..99).to_a]
316
+ assert_equal(nil, a[10,10] = nil)
317
+ assert_equal(@cls[*(0..9).to_a] + @cls[*(20..99).to_a], a)
318
+
319
+ a = @cls[*(0..99).to_a]
320
+ assert_equal(nil, a[-1, 1] = nil)
321
+ assert_equal(@cls[*(0..98).to_a], a)
322
+
323
+ a = @cls[*(0..99).to_a]
324
+ assert_equal(nil, a[-10, 10] = nil)
325
+ assert_equal(@cls[*(0..89).to_a], a)
326
+
327
+ a = @cls[*(0..99).to_a]
328
+ assert_equal(nil, a[0,1000] = nil)
329
+ assert_equal(@cls[] , a)
330
+
331
+ a = @cls[*(0..99).to_a]
332
+ assert_equal(nil, a[10..19] = nil)
333
+ assert_equal(@cls[*(0..9).to_a] + @cls[*(20..99).to_a], a)
334
+ =end
335
+
336
+ # Changes: should have @cls in definition
337
+
338
+ a = @cls[1, 2, 3]
339
+ a[1, 0] = a
340
+ #assert_equal([1, 1, 2, 3, 2, 3], a)
341
+ assert_equal(@cls[1, 1, 2, 3, 2, 3], a)
342
+
343
+ a = @cls[1, 2, 3]
344
+ a[-1, 0] = a
345
+ #assert_equal([1, 2, 1, 2, 3, 3], a)
346
+ assert_equal(@cls[1, 2, 1, 2, 3, 3], a)
347
+ end
348
+
349
+ def test_concat
350
+ # Currently there are issues with this...
351
+
352
+ # assert_equal(@cls[1, 2, 3, 4], @cls[1, 2].concat(@cls[3, 4]))
353
+ # assert_equal(@cls[1, 2, 3, 4], @cls[].concat(@cls[1, 2, 3, 4]))
354
+ # assert_equal(@cls[1, 2, 3, 4], @cls[1, 2, 3, 4].concat(@cls[]))
355
+ # assert_equal(@cls[], @cls[].concat(@cls[]))
356
+ # assert_equal(@cls[@cls[1, 2], @cls[3, 4]], @cls[@cls[1, 2]].concat(@cls[@cls[3, 4]]))
357
+ #
358
+ # a = @cls[1, 2, 3]
359
+ # a.concat(a)
360
+ # assert_equal([1, 2, 3, 1, 2, 3], a)
361
+ end
362
+
363
+ def test_eql?
364
+ assert(@cls[].eql?(@cls[]))
365
+ assert(@cls[1].eql?(@cls[1]))
366
+ assert(@cls[1, 1, 2, 2].eql?(@cls[1, 1, 2, 2]))
367
+
368
+ # Changes: converting values to strings and back to
369
+ # numerics causes equal values to be equal, regardless
370
+ # of whether they were entered as different types initially
371
+ #assert(!@cls[1.0, 1.0, 2.0, 2.0].eql?(@cls[1, 1, 2, 2]))
372
+ assert(@cls[1.0, 1.0, 2.0, 2.0].eql?(@cls[1, 1, 2, 2]))
373
+ end
374
+
375
+ def test_to_a
376
+ a = @cls[ 1, 2, 3 ]
377
+ a_id = a.__id__
378
+ assert_equal(a, a.to_a)
379
+
380
+ # Changes: can't do this comparison by object id
381
+ #assert_equal(a_id, a.to_a.__id__)
382
+ end
383
+
384
+
385
+ #######################
386
+ # Benchmark tests
387
+ #######################
388
+
389
+ #
390
+ # benchmarks
391
+ #
392
+
393
+ def ea_bm_test(mode, length=20, array=nil, &block)
394
+ benchmark_test(length) do |x|
395
+ unless array
396
+ array = []
397
+ 1.upto(10000) {|i| array << i.to_s }
398
+ end
399
+
400
+ begin
401
+ ea = ExtArr[*array]
402
+ yield(x, "", ea)
403
+ ensure
404
+ ea.close if index
405
+ end
406
+
407
+ yield(x, "array reference", array)
408
+ end
409
+
410
+ array
411
+ end
412
+
413
+ def test_element_reference_speed_for_ext_arr
414
+ n = 10
415
+ ea_bm_test('r') do |x, type, ea|
416
+ puts type
417
+
418
+ x.report("#{n}kx [index]") { (n*1000).times { ea[1000] } }
419
+ x.report("#{n}kx [range]") { (n*1000).times { ea[1000..1000] } }
420
+ x.report("#{n}kx [s,1]") { (n*1000).times { ea[1000, 1] } }
421
+ x.report("#{n}kx [s,10]") { (n*1000).times { ea[1000, 10] } }
422
+ #x.report("#{n}kx [s,100]") { (n*1000).times { ea[1000, 100] } }
423
+
424
+ puts
425
+ end
426
+ end
427
+
428
+ def test_element_assignment_speed_for_ext_arr
429
+ ea_bm_test('r+') do |x, type, index|
430
+ puts type
431
+
432
+ n = 1
433
+ obj = "abcde"
434
+
435
+ x.report("#{n}kx [index]=") do
436
+ (n*1000).times { ea[1000] = obj }
437
+ end
438
+ x.report("#{n}kx [range]=") do
439
+ (n*1000).times { ea[1000..1000] = [obj] }
440
+ end
441
+ x.report("#{n}kx [s,1]=") do
442
+ (n*1000).times { ea[1000,1] = [obj] }
443
+ end
444
+
445
+ puts
446
+ end
447
+ end
448
+
449
+ end
450
+
451
+ class HOLD
452
+
453
+ #
454
+ # scan collect
455
+ #
456
+
457
+ def test_scan_collect_collects_block_results
458
+ aio_test do |aio|
459
+ indicies = []
460
+ offsets = []
461
+ result = aio.scan_collect do |scanner, offset, index|
462
+ offsets << offset
463
+ indicies << index
464
+ scanner.scan(/\w/)
465
+ end
466
+
467
+ assert_equal [0, 0, 0], offsets
468
+ assert_equal index, indicies
469
+ assert_equal ['a','d', 'f'], result
470
+
471
+ # now with reduced chunk size
472
+ aio.chunk_size = 3
473
+ indicies = []
474
+ offsets = []
475
+ result = aio.scan_collect do |scanner, offset, index|
476
+ offsets << offset
477
+ indicies << index
478
+ scanner.scan(/\w/)
479
+ end
480
+
481
+ assert_equal [0, 3, 5], offsets
482
+ assert_equal index, indicies
483
+ assert_equal ['a','d', 'f'], result
484
+ end
485
+ end
486
+
487
+ def test_scan_collect_with_subsets
488
+ aio_test do |aio|
489
+ case_test(
490
+ #[0] => ['a'],
491
+ #[1] => ['a'],
492
+ #[-4] => nil,
493
+ [0..1] => ['a','d'],
494
+ [0...1] => ['a'],
495
+ [0...0] => [],
496
+ [0, 2] => ['a','d'],
497
+ [0, 0] => []
498
+ ) do |subset, expected|
499
+ indicies = []
500
+ result = aio.scan_collect(aio.index[*subset]) do |scanner, offset, index|
501
+ indicies << index
502
+ scanner.scan(/\w/)
503
+ end
504
+
505
+ assert_equal index[*subset], indicies, subset
506
+ assert_equal expected, result, subset
507
+ end
508
+ end
509
+ end
510
+
511
+ def test_scan_collect_raises_error_on_scan_past_index_end
512
+ aio_test do |aio|
513
+ assert_raise(RuntimeError) do
514
+ aio.scan_collect do |scanner, offset, index|
515
+ scanner.skip_until(/$/)
516
+ end
517
+ end
518
+ end
519
+ end
520
+
521
+ #
522
+ # chunk test
523
+ #
524
+
525
+ def test_chunk_chunks_on_io_length_not_length
526
+ saio = setup_saio
527
+ assert_equal 3, saio.length
528
+ assert_equal string.length, saio.io.length
529
+
530
+ saio.chunk do |o, l|
531
+ assert_equal [0, saio.io.length], [o,l]
532
+ end
533
+ end
534
+ end