scout-gear 7.2.0 → 7.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +37 -3
  3. data/VERSION +1 -1
  4. data/lib/scout/concurrent_stream.rb +9 -8
  5. data/lib/scout/exceptions.rb +1 -0
  6. data/lib/scout/log/color.rb +0 -1
  7. data/lib/scout/log/progress/util.rb +65 -0
  8. data/lib/scout/misc/helper.rb +31 -0
  9. data/lib/scout/misc/monitor.rb +1 -1
  10. data/lib/scout/misc.rb +1 -0
  11. data/lib/scout/open/stream.rb +21 -27
  12. data/lib/scout/persist.rb +42 -28
  13. data/lib/scout/semaphore.rb +8 -1
  14. data/lib/scout/tsv/dumper.rb +13 -8
  15. data/lib/scout/tsv/index.rb +127 -15
  16. data/lib/scout/tsv/open.rb +128 -0
  17. data/lib/scout/tsv/parser.rb +70 -43
  18. data/lib/scout/tsv/path.rb +4 -4
  19. data/lib/scout/tsv/persist/adapter.rb +52 -33
  20. data/lib/scout/tsv/persist/fix_width_table.rb +324 -0
  21. data/lib/scout/tsv/persist/serialize.rb +117 -0
  22. data/lib/scout/tsv/persist/tokyocabinet.rb +3 -3
  23. data/lib/scout/tsv/persist.rb +0 -2
  24. data/lib/scout/tsv/traverse.rb +130 -35
  25. data/lib/scout/tsv/util/filter.rb +303 -0
  26. data/lib/scout/tsv/util/process.rb +73 -0
  27. data/lib/scout/tsv/util/select.rb +220 -0
  28. data/lib/scout/tsv/util.rb +77 -19
  29. data/lib/scout/tsv.rb +2 -2
  30. data/lib/scout/work_queue/worker.rb +1 -1
  31. data/lib/scout/workflow/definition.rb +8 -0
  32. data/lib/scout/workflow/step/info.rb +4 -0
  33. data/lib/scout/workflow/step/progress.rb +14 -0
  34. data/lib/scout/workflow/step.rb +10 -5
  35. data/lib/scout/workflow/task.rb +8 -4
  36. data/lib/scout/workflow/usage.rb +2 -0
  37. data/scout-gear.gemspec +33 -10
  38. data/scout_commands/workflow/task +3 -2
  39. data/scout_commands/workflow/task_old +2 -2
  40. data/test/scout/open/test_stream.rb +1 -1
  41. data/test/scout/test_persist.rb +61 -0
  42. data/test/scout/test_tmpfile.rb +1 -1
  43. data/test/scout/test_tsv.rb +10 -1
  44. data/test/scout/test_work_queue.rb +1 -0
  45. data/test/scout/tsv/persist/test_adapter.rb +10 -0
  46. data/test/scout/tsv/persist/test_fix_width_table.rb +134 -0
  47. data/test/scout/tsv/test_index.rb +94 -2
  48. data/test/scout/tsv/test_open.rb +9 -0
  49. data/test/scout/tsv/test_parser.rb +28 -3
  50. data/test/scout/tsv/test_persist.rb +7 -0
  51. data/test/scout/tsv/test_traverse.rb +110 -3
  52. data/test/scout/tsv/test_util.rb +23 -0
  53. data/test/scout/tsv/util/test_filter.rb +188 -0
  54. data/test/scout/tsv/util/test_process.rb +47 -0
  55. data/test/scout/tsv/util/test_select.rb +44 -0
  56. data/test/scout/work_queue/test_worker.rb +63 -6
  57. data/test/scout/workflow/step/test_load.rb +3 -3
  58. data/test/scout/workflow/test_step.rb +10 -10
  59. data/test/test_helper.rb +3 -1
  60. metadata +19 -6
@@ -27,7 +27,7 @@ class WorkQueue
27
27
  rescue Interrupt
28
28
  rescue Exception
29
29
  output.write WorkerException.new($!, Process.pid)
30
- exit -1
30
+ Kernel.exit -1
31
31
  end
32
32
  end
33
33
  end
@@ -164,4 +164,12 @@ module Workflow
164
164
  end
165
165
 
166
166
  alias dep_task task_alias
167
+
168
+ def export(*args)
169
+ end
170
+
171
+ alias export_synchronous export
172
+ alias export_asynchronous export
173
+ alias export_exec export
174
+ alias export_stream export
167
175
  end
@@ -101,4 +101,8 @@ class Step
101
101
  def running?
102
102
  ! done? && (info[:pid] && Misc.pid_alive?(info[:pid]))
103
103
  end
104
+
105
+ def exception
106
+ info[:exception]
107
+ end
104
108
  end
@@ -0,0 +1,14 @@
1
+ class Step
2
+ def progress_bar(msg = "Progress", options = nil)
3
+ if Hash === msg and options.nil?
4
+ options = msg
5
+ msg = nil
6
+ end
7
+ options = {} if options.nil?
8
+
9
+ max = options[:max]
10
+ Open.mkdir files_dir
11
+ Log::ProgressBar.new_bar(max, {:desc => msg, :file => (@exec ? nil : file(:progress))}.merge(options))
12
+ end
13
+ end
14
+
@@ -6,6 +6,7 @@ require_relative 'step/file'
6
6
  require_relative 'step/dependencies'
7
7
  require_relative 'step/provenance'
8
8
  require_relative 'step/config'
9
+ require_relative 'step/progress'
9
10
 
10
11
  class Step
11
12
 
@@ -78,7 +79,9 @@ class Step
78
79
  :inputs => inputs, :type => type,
79
80
  :dependencies => dependencies.collect{|d| d.path }
80
81
 
81
- exec
82
+ @result = exec
83
+ @result = @result.respond_to?(:stream) ? @result.stream : @result
84
+ @result
82
85
  rescue Exception => e
83
86
  merge_info :status => :error, :exception => e
84
87
  raise e
@@ -104,6 +107,7 @@ class Step
104
107
  end
105
108
  end
106
109
  end
110
+ @result
107
111
  end
108
112
 
109
113
  def done?
@@ -111,10 +115,10 @@ class Step
111
115
  end
112
116
 
113
117
  def streaming?
114
- @take_stream || IO === @result || StringIO === @result
118
+ @take_stream || IO === @result || StringIO === @result
115
119
  end
116
120
 
117
- def get_stream
121
+ def stream
118
122
  synchronize do
119
123
  if streaming? && ! @result.nil?
120
124
  if @result.next
@@ -137,8 +141,9 @@ class Step
137
141
  end
138
142
 
139
143
  def join
140
- stream = get_stream if streaming?
141
- Open.consume_stream(stream, false) if stream
144
+ io = self.stream if streaming?
145
+ Open.consume_stream(io, false) if io
146
+ self
142
147
  end
143
148
 
144
149
  def produce
@@ -1,4 +1,5 @@
1
1
  require_relative '../meta_extension'
2
+ require_relative '../named_array'
2
3
  require_relative 'step'
3
4
  require_relative 'task/inputs'
4
5
 
@@ -24,7 +25,7 @@ module Task
24
25
  return inputs if deps.nil?
25
26
  deps.inject(inputs) do |acc,dep|
26
27
  workflow, task = dep
27
- next if workflow.nil?
28
+ next acc if workflow.nil? || task.nil?
28
29
  acc += workflow.tasks[task].recursive_inputs
29
30
  end
30
31
  end
@@ -144,13 +145,16 @@ module Task
144
145
 
145
146
  if non_default_inputs.any?
146
147
  hash = Misc.digest(:inputs => input_hash, :dependencies => dependencies)
147
- Log.debug "Hash #{name} - #{hash}: #{Misc.digest_str(:inputs => inputs, :non_default_inputs => non_default_inputs, :dependencies => dependencies)}"
148
+ Log.debug "Hash #{name} - #{hash}: #{Log.fingerprint(:inputs => inputs, :non_default_inputs => non_default_inputs, :dependencies => dependencies)}"
148
149
  id = [id, hash] * "_"
149
150
  end
150
151
 
151
152
  path = directory[id]
152
153
 
153
- NamedArray.setup(inputs, @inputs.collect{|i| i[0] }) if @inputs
154
- Step.new path.find, inputs, dependencies, &self
154
+ Persist.memory(path) do
155
+ Log.debug "Creating job #{path} #{Log.fingerprint inputs} #{Log.fingerprint dependencies}"
156
+ NamedArray.setup(inputs, @inputs.collect{|i| i[0] }) if @inputs
157
+ Step.new path.find, inputs, dependencies, &self
158
+ end
155
159
  end
156
160
  end
@@ -20,6 +20,7 @@ module Task
20
20
  seen = inputs.collect{|name,_| name }
21
21
  dep_inputs = {}
22
22
  deps.each do |dep_workflow,task_name|
23
+ next if task_name.nil?
23
24
  task = dep_workflow.tasks[task_name]
24
25
  next if task.inputs.nil?
25
26
  inputs = task.inputs.reject{|name, _| seen.include? name }
@@ -122,6 +123,7 @@ module Workflow
122
123
  next if seen.include? dep
123
124
  seen << dep
124
125
  workflow, task, *rest = dep
126
+ next if task.nil?
125
127
 
126
128
  key = [workflow, task]
127
129
 
data/scout-gear.gemspec CHANGED
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: scout-gear 7.2.0 ruby lib
5
+ # stub: scout-gear 7.3.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "scout-gear".freeze
9
- s.version = "7.2.0"
9
+ s.version = "7.3.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["Miguel Vazquez".freeze]
14
- s.date = "2023-05-09"
14
+ s.date = "2023-05-12"
15
15
  s.description = "Temporary files, logs, etc.".freeze
16
16
  s.email = "mikisvaz@gmail.com".freeze
17
17
  s.executables = ["scout".freeze]
@@ -50,6 +50,7 @@ Gem::Specification.new do |s|
50
50
  "lib/scout/misc/digest.rb",
51
51
  "lib/scout/misc/filesystem.rb",
52
52
  "lib/scout/misc/format.rb",
53
+ "lib/scout/misc/helper.rb",
53
54
  "lib/scout/misc/insist.rb",
54
55
  "lib/scout/misc/monitor.rb",
55
56
  "lib/scout/misc/system.rb",
@@ -85,13 +86,19 @@ Gem::Specification.new do |s|
85
86
  "lib/scout/tsv.rb",
86
87
  "lib/scout/tsv/dumper.rb",
87
88
  "lib/scout/tsv/index.rb",
89
+ "lib/scout/tsv/open.rb",
88
90
  "lib/scout/tsv/parser.rb",
89
91
  "lib/scout/tsv/path.rb",
90
92
  "lib/scout/tsv/persist.rb",
91
93
  "lib/scout/tsv/persist/adapter.rb",
94
+ "lib/scout/tsv/persist/fix_width_table.rb",
95
+ "lib/scout/tsv/persist/serialize.rb",
92
96
  "lib/scout/tsv/persist/tokyocabinet.rb",
93
97
  "lib/scout/tsv/traverse.rb",
94
98
  "lib/scout/tsv/util.rb",
99
+ "lib/scout/tsv/util/filter.rb",
100
+ "lib/scout/tsv/util/process.rb",
101
+ "lib/scout/tsv/util/select.rb",
95
102
  "lib/scout/work_queue.rb",
96
103
  "lib/scout/work_queue/socket.rb",
97
104
  "lib/scout/work_queue/worker.rb",
@@ -104,6 +111,7 @@ Gem::Specification.new do |s|
104
111
  "lib/scout/workflow/step/file.rb",
105
112
  "lib/scout/workflow/step/info.rb",
106
113
  "lib/scout/workflow/step/load.rb",
114
+ "lib/scout/workflow/step/progress.rb",
107
115
  "lib/scout/workflow/step/provenance.rb",
108
116
  "lib/scout/workflow/task.rb",
109
117
  "lib/scout/workflow/task/inputs.rb",
@@ -165,13 +173,18 @@ Gem::Specification.new do |s|
165
173
  "test/scout/test_work_queue.rb",
166
174
  "test/scout/test_workflow.rb",
167
175
  "test/scout/tsv/persist/test_adapter.rb",
176
+ "test/scout/tsv/persist/test_fix_width_table.rb",
168
177
  "test/scout/tsv/persist/test_tokyocabinet.rb",
169
178
  "test/scout/tsv/test_dumper.rb",
170
179
  "test/scout/tsv/test_index.rb",
180
+ "test/scout/tsv/test_open.rb",
171
181
  "test/scout/tsv/test_parser.rb",
172
182
  "test/scout/tsv/test_persist.rb",
173
183
  "test/scout/tsv/test_traverse.rb",
174
184
  "test/scout/tsv/test_util.rb",
185
+ "test/scout/tsv/util/test_filter.rb",
186
+ "test/scout/tsv/util/test_process.rb",
187
+ "test/scout/tsv/util/test_select.rb",
175
188
  "test/scout/work_queue/test_socket.rb",
176
189
  "test/scout/work_queue/test_worker.rb",
177
190
  "test/scout/workflow/step/test_dependencies.rb",
@@ -190,15 +203,25 @@ Gem::Specification.new do |s|
190
203
  ]
191
204
  s.homepage = "http://github.com/mikisvaz/scout-gear".freeze
192
205
  s.licenses = ["MIT".freeze]
193
- s.rubygems_version = "3.4.11".freeze
206
+ s.rubygems_version = "3.2.15".freeze
194
207
  s.summary = "basic gear for scouts".freeze
195
208
 
196
- s.specification_version = 4
209
+ if s.respond_to? :specification_version then
210
+ s.specification_version = 4
211
+ end
197
212
 
198
- s.add_runtime_dependency(%q<term-ansicolor>.freeze, [">= 0"])
199
- s.add_development_dependency(%q<rdoc>.freeze, ["~> 3.12"])
200
- s.add_development_dependency(%q<bundler>.freeze, ["~> 1.0"])
201
- s.add_development_dependency(%q<juwelier>.freeze, ["~> 2.1.0"])
202
- s.add_development_dependency(%q<simplecov>.freeze, [">= 0"])
213
+ if s.respond_to? :add_runtime_dependency then
214
+ s.add_runtime_dependency(%q<term-ansicolor>.freeze, [">= 0"])
215
+ s.add_development_dependency(%q<rdoc>.freeze, ["~> 3.12"])
216
+ s.add_development_dependency(%q<bundler>.freeze, ["~> 1.0"])
217
+ s.add_development_dependency(%q<juwelier>.freeze, ["~> 2.1.0"])
218
+ s.add_development_dependency(%q<simplecov>.freeze, [">= 0"])
219
+ else
220
+ s.add_dependency(%q<term-ansicolor>.freeze, [">= 0"])
221
+ s.add_dependency(%q<rdoc>.freeze, ["~> 3.12"])
222
+ s.add_dependency(%q<bundler>.freeze, ["~> 1.0"])
223
+ s.add_dependency(%q<juwelier>.freeze, ["~> 2.1.0"])
224
+ s.add_dependency(%q<simplecov>.freeze, [">= 0"])
225
+ end
203
226
  end
204
227
 
@@ -24,7 +24,7 @@ raise MissingParameterException.new :workflow if workflow_name.nil?
24
24
 
25
25
  workflow = Workflow.require_workflow workflow_name
26
26
  task_name = task_name.to_sym if task_name
27
- task = workflow.tasks[task_name.to_sym]
27
+ task = workflow.tasks[task_name.to_sym] if task_name
28
28
 
29
29
  options[:help] = true if task.nil?
30
30
 
@@ -51,11 +51,12 @@ else
51
51
  job.run unless job.done?
52
52
 
53
53
  if options[:print_filepath]
54
+ job.join
54
55
  path = job.path
55
56
  path = path.find if Path === path
56
57
  puts path
57
58
  else
58
- if ! ((c = Open.consume_stream(job.get_stream, false, STDOUT, false)) && c.end_with?("\n"))
59
+ if ! ((c = Open.consume_stream(job.stream, false, STDOUT, false)) && c.end_with?("\n"))
59
60
  puts
60
61
  end
61
62
  end
@@ -656,12 +656,12 @@ when (defined?(RemoteStep) and RemoteStep)
656
656
  end
657
657
  when Step
658
658
  if res.streaming?
659
- io = TSV.get_stream res
659
+ io = TSV.stream res
660
660
  Misc.consume_stream(io, false, out)
661
661
  io.join if io.respond_to? :join
662
662
  elsif IO === res.result
663
663
  begin
664
- io = res.get_stream
664
+ io = res.stream
665
665
  Misc.consume_stream(io, false, out)
666
666
  io.join if io.respond_to? :join
667
667
  rescue Aborted, Interrupt
@@ -5,7 +5,7 @@ require 'scout/path'
5
5
  require 'scout/open'
6
6
 
7
7
  class TestOpenStream < Test::Unit::TestCase
8
- def test_consume_stream
8
+ def test_stream
9
9
  content =<<-EOF
10
10
  1
11
11
  2
@@ -95,6 +95,67 @@ class TestPersist < Test::Unit::TestCase
95
95
  end
96
96
  end
97
97
 
98
+ def test_concurrent
99
+ num = 10
100
+
101
+ s = 0.01
102
+ 10.times do
103
+ TmpFile.with_file do |file|
104
+ output1 = file + '.output1'
105
+ output2 = file + '.output2'
106
+ pid1 = Process.fork do
107
+ Open.purge_pipes
108
+ sleep rand/10.0
109
+ io = Persist.persist("test", :string, :path => file) do
110
+ Open.open_pipe do |sin|
111
+ num.times do |i|
112
+ sin.puts "line-#{i}-#{Process.pid}"
113
+ sleep s
114
+ end
115
+ end
116
+ end
117
+ if IO === io
118
+ Open.consume_stream(io, false)
119
+ else
120
+ Open.write(output1, io)
121
+ end
122
+ end
123
+ pid2 = Process.fork do
124
+ Open.purge_pipes
125
+ sleep rand/10.0
126
+ io = Persist.persist("test", :string, :path => file) do
127
+ Open.open_pipe do |sin|
128
+ num.times do |i|
129
+ sin.puts "line-#{i}-#{Process.pid}"
130
+ sleep s
131
+ end
132
+ end
133
+ end
134
+ if IO === io
135
+ Open.consume_stream(io, false)
136
+ else
137
+ Open.write(output2, io)
138
+ end
139
+ end
140
+ Process.wait
141
+ Process.wait
142
+
143
+ assert File.exist?(output1) || File.exist?(output2)
144
+ [pid1, pid2].zip([output2, output1]).each do |pid, found|
145
+ next unless File.exist?(found)
146
+ assert Open.read(found).include? "-#{pid}\n"
147
+ end
148
+ [pid1, pid2].zip([output1, output2]).each do |pid, found|
149
+ next unless File.exist?(found)
150
+ refute Open.read(found).include? "-#{pid}\n"
151
+ end
152
+ Open.rm file
153
+ Open.rm output1
154
+ Open.rm output2
155
+ end
156
+ end
157
+ end
158
+
98
159
  def __test_speed
99
160
  times = 100_000
100
161
  TmpFile.with_file do |tmpfile|
@@ -10,7 +10,7 @@ class TestTmpFile < Test::Unit::TestCase
10
10
  def test_do_tmp_file
11
11
  content = "Hello World!"
12
12
  TmpFile.with_file(content) do |file|
13
- assert_equal_path content, File.open(file).read
13
+ assert_equal content, File.open(file).read
14
14
  end
15
15
  end
16
16
 
@@ -61,7 +61,15 @@ row2 a a id3
61
61
  EOF
62
62
 
63
63
  tsv = TmpFile.with_file(content) do |filename|
64
- TSV.open(filename, :persist => true)
64
+ TSV.open(filename, :persist => false)
65
+ end
66
+
67
+ assert_include tsv.keys, 'row1'
68
+ assert_include tsv.keys, 'row2'
69
+ assert_equal %w(A a), tsv["row2"][0]
70
+
71
+ tsv = TmpFile.with_file(content) do |filename|
72
+ TSV.open(filename, :persist => true, :merge => true)
65
73
  end
66
74
 
67
75
  assert tsv.respond_to?(:persistence_class)
@@ -69,6 +77,7 @@ row2 a a id3
69
77
 
70
78
  assert_include tsv.keys, 'row1'
71
79
  assert_include tsv.keys, 'row2'
80
+ assert_equal %w(A a), tsv["row2"][0]
72
81
  end
73
82
  end
74
83
 
@@ -93,6 +93,7 @@ class TestWorkQueue < Test::Unit::TestCase
93
93
  num = 100
94
94
  reps = 10_000
95
95
 
96
+ sss 0
96
97
  q = WorkQueue.new num do |obj|
97
98
  raise ScoutException if rand < 0.1
98
99
  [Process.pid.to_s, obj.to_s] * " "
@@ -30,5 +30,15 @@ class TestTSVAdapter < Test::Unit::TestCase
30
30
  assert_equal [["a", %w(1 2 3)], ["b", %w(11 22 33)]], tsv.sort
31
31
  assert_equal [["b", %w(11 22 33)], ["a", %w(1 2 3)]], tsv.sort_by{|k,v| -v[0].to_i }
32
32
  end
33
+
34
+ def test_serializer
35
+ tsv = TSV.setup({}, :type => :list, :key_field => "Key", :fields => %w(one two three))
36
+ tsv.type = :list
37
+ tsv.extend TSVAdapter
38
+ tsv.serializer = :integer_array
39
+ tsv["a"] = [1, 2, 3]
40
+
41
+ assert_equal [1, 2, 3], tsv["a"]
42
+ end
33
43
  end
34
44
 
@@ -0,0 +1,134 @@
1
+ require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
2
+ require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
3
+
4
+ require 'scout/tsv'
5
+ class TestFixWidthTable < Test::Unit::TestCase
6
+ def load_data(data)
7
+ tsv = TSV.open(data, type: :list, :sep=>":", :cast => proc{|e| e =~ /(\s*)(_*)/; ($1.length..($1.length + $2.length - 1))})
8
+ tsv.add_field "Start" do |key, values|
9
+ values["Range"].first
10
+ end
11
+ tsv.add_field "End" do |key, values|
12
+ values["Range"].last
13
+ end
14
+
15
+ tsv = tsv.slice ["Start", "End"]
16
+
17
+ tsv
18
+ end
19
+
20
+ def test_options
21
+ TmpFile.with_file do |filename|
22
+ f = FixWidthTable.new filename, 100, true
23
+ f.close
24
+
25
+ f1 = FixWidthTable.new filename, 100, false
26
+
27
+ assert_equal true, f1.range
28
+ end
29
+ end
30
+
31
+ def test_add
32
+ TmpFile.with_file do |filename|
33
+ f = FixWidthTable.new filename, 100, true
34
+ f.add [1,2,0], "test1"
35
+ f.add [3,4,0], "test2"
36
+ f.read
37
+
38
+ assert_equal 1, f.idx_pos(0)
39
+ assert_equal 3, f.idx_pos(1)
40
+ assert_equal 2, f.idx_pos_end(0)
41
+ assert_equal 4, f.idx_pos_end(1)
42
+ assert_equal 0, f.idx_overlap(0)
43
+ assert_equal 0, f.idx_overlap(1)
44
+ assert_equal "test1", f.idx_value(0)
45
+ assert_equal "test2", f.idx_value(1)
46
+
47
+ end
48
+
49
+ end
50
+
51
+ def test_point
52
+ data =<<-EOF
53
+ #: :sep=/\\s+/#:type=:single#:cast=:to_i
54
+ #ID Pos
55
+ a 1
56
+ b 10
57
+ c 20
58
+ d 12
59
+ e 26
60
+ f 11
61
+ g 25
62
+ EOF
63
+ TmpFile.with_file(data) do |datafile|
64
+ tsv = TSV.open datafile
65
+ TmpFile.with_file do |filename|
66
+ f = FixWidthTable.new filename, 100, false
67
+ f.add_point tsv
68
+ f.read
69
+
70
+ assert_equal %w(), f[0].sort
71
+ assert_equal %w(b), f[10].sort
72
+ assert_equal %w(a b c d f), f[(0..20)].sort
73
+ end
74
+ end
75
+ end
76
+
77
+ def test_range
78
+ data =<<-EOF
79
+ ##012345678901234567890
80
+ #ID:Range
81
+ a: ______
82
+ b: ______
83
+ c: _______
84
+ d: ____
85
+ e: ______
86
+ f: ___
87
+ g: ____
88
+ EOF
89
+ TmpFile.with_file(data) do |datafile|
90
+ tsv = load_data(datafile)
91
+ TmpFile.with_file do |filename|
92
+ f = FixWidthTable.new filename, 100, true
93
+ f.add_range tsv
94
+ f.read
95
+
96
+ assert_equal %w(), f[0].sort
97
+ assert_equal %w(b), f[1].sort
98
+ assert_equal %w(), f[20].sort
99
+ assert_equal %w(), f[(20..100)].sort
100
+ assert_equal %w(a b d), f[3].sort
101
+ assert_equal %w(a b c d e), f[(3..4)].sort
102
+ assert_equal %w(a c e), f[7].sort
103
+ end
104
+ end
105
+ end
106
+
107
+
108
+ def test_range_pos
109
+ data =<<-EOF
110
+ ##012345678901234567890
111
+ #ID:Range
112
+ a: ______
113
+ b: ______
114
+ c: _______
115
+ d: ____
116
+ e: ______
117
+ f: ___
118
+ g: ____
119
+ EOF
120
+ TmpFile.with_file(data) do |datafile|
121
+ tsv = load_data(datafile)
122
+ TmpFile.with_file do |filename|
123
+ f = FixWidthTable.new filename, 100, true
124
+ f.add_range tsv
125
+ f.read
126
+
127
+ assert_equal %w(), f.overlaps(0).sort
128
+ assert_equal %w(1:6), f.overlaps(1).sort
129
+ assert_equal %w(1:6:b), f.overlaps(1, true).sort
130
+ end
131
+ end
132
+ end
133
+ end
134
+