external 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.
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