sequence 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.
- data/COPYING +58 -0
- data/GPL +340 -0
- data/Manifest.txt +36 -0
- data/README.txt +320 -0
- data/Rakefile +32 -0
- data/lib/assert.rb +16 -0
- data/lib/sequence/arraylike.rb +57 -0
- data/lib/sequence/buffered.rb +188 -0
- data/lib/sequence/circular.rb +272 -0
- data/lib/sequence/enum.rb +260 -0
- data/lib/sequence/file.rb +172 -0
- data/lib/sequence/functional.rb +152 -0
- data/lib/sequence/generator.rb +290 -0
- data/lib/sequence/indexed.rb +234 -0
- data/lib/sequence/io.rb +102 -0
- data/lib/sequence/list.rb +292 -0
- data/lib/sequence/ofhash.rb +38 -0
- data/lib/sequence/ofobjectivars.rb +29 -0
- data/lib/sequence/ofobjectmethods.rb +87 -0
- data/lib/sequence/position.rb +100 -0
- data/lib/sequence/reversed.rb +180 -0
- data/lib/sequence/shifting.rb +190 -0
- data/lib/sequence/singleitem.rb +50 -0
- data/lib/sequence/stringlike.rb +482 -0
- data/lib/sequence/subseq.rb +90 -0
- data/lib/sequence/usedata.rb +35 -0
- data/lib/sequence/version.rb +5 -0
- data/lib/sequence.rb +721 -0
- data/lib/weakrefset.rb +254 -0
- data/test/test.rb +609 -0
- data/test/test_all.rb +6 -0
- data/test/test_changes.rb +44 -0
- data/test/test_circulars.rb +89 -0
- data/test/test_rexscan.rb +899 -0
- data/test/test_seqrex.rb +204 -0
- data/test/test_sequences.rb +106 -0
- metadata +90 -0
@@ -0,0 +1,899 @@
|
|
1
|
+
# Copyright (C) 2006 Caleb Clausen
|
2
|
+
# Distributed under the terms of Ruby's license.
|
3
|
+
$VERBOSE=1
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
|
7
|
+
require 'sequence'
|
8
|
+
require 'sequence/indexed'
|
9
|
+
require 'sequence/reversed'
|
10
|
+
require 'sequence/position'
|
11
|
+
require 'sequence/circular'
|
12
|
+
require 'sequence/buffered'
|
13
|
+
require 'sequence/shifting'
|
14
|
+
require 'sequence/file'
|
15
|
+
require 'sequence/list'
|
16
|
+
require 'sequence/io'
|
17
|
+
require 'tempfile'
|
18
|
+
|
19
|
+
|
20
|
+
BEGIN {
|
21
|
+
if seedstr=ENV['SEED']
|
22
|
+
seed=seedstr.to_i
|
23
|
+
srand seed
|
24
|
+
else
|
25
|
+
rand;
|
26
|
+
seed=srand
|
27
|
+
end
|
28
|
+
|
29
|
+
puts "random seed is #{seed}"
|
30
|
+
}
|
31
|
+
|
32
|
+
$Debug=true
|
33
|
+
|
34
|
+
class SequenceTests
|
35
|
+
|
36
|
+
DATA="foo\nbar baz that tough guy talk\ndon't make you a dog"
|
37
|
+
DATA.freeze
|
38
|
+
OFFSET=12
|
39
|
+
|
40
|
+
|
41
|
+
class Indexed <Test::Unit::TestCase
|
42
|
+
def a_seq
|
43
|
+
#assert_equal 52==DATA.size
|
44
|
+
seq= Sequence::Indexed.new(DATA.dup)
|
45
|
+
seq.move(OFFSET)
|
46
|
+
return seq
|
47
|
+
end
|
48
|
+
def absolutes_always_fail; false end
|
49
|
+
|
50
|
+
#forward decls
|
51
|
+
def nop; end
|
52
|
+
MOVEPOSMETHODS=%w[test_nearbegin test_nearend
|
53
|
+
test_pos
|
54
|
+
test_pos=
|
55
|
+
test_scanning
|
56
|
+
test_readahead
|
57
|
+
test_read
|
58
|
+
test_slice
|
59
|
+
test_slice_empty
|
60
|
+
]
|
61
|
+
MODIFYMETHODS=%w[
|
62
|
+
test_insert
|
63
|
+
test_delete
|
64
|
+
test_modify
|
65
|
+
test_insert_empty
|
66
|
+
test_delete_empty
|
67
|
+
test_insert_start
|
68
|
+
test_delete_start
|
69
|
+
test_insert_end
|
70
|
+
test_delete_end
|
71
|
+
test_randomized_methods_some_more
|
72
|
+
test_write
|
73
|
+
test_writeback
|
74
|
+
test_write_and_read_joints
|
75
|
+
test_insert_and_read_joints
|
76
|
+
test_delete_and_read_joint
|
77
|
+
test_modify_and_read_joints
|
78
|
+
test_pos_munging
|
79
|
+
]
|
80
|
+
(MOVEPOSMETHODS+MODIFYMETHODS).each{|m| alias_method m, :nop }
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
class Position <Indexed
|
87
|
+
def a_seq
|
88
|
+
super.position
|
89
|
+
end
|
90
|
+
end
|
91
|
+
class SubSeq1 <Indexed
|
92
|
+
def a_seq
|
93
|
+
cu=super.subseq(0..-1)
|
94
|
+
cu.pos=OFFSET
|
95
|
+
cu
|
96
|
+
end
|
97
|
+
end
|
98
|
+
class SubSeq2 <Indexed
|
99
|
+
def a_seq
|
100
|
+
seq= Sequence::Indexed.new("0123456789#{DATA}0123456789")
|
101
|
+
seq = seq. subseq(10...-10)
|
102
|
+
seq.pos=OFFSET
|
103
|
+
return seq
|
104
|
+
end
|
105
|
+
end
|
106
|
+
class SubSeq3 <Indexed
|
107
|
+
def a_seq
|
108
|
+
seq = Sequence::Indexed.new("0123456789#{DATA}0123456789")
|
109
|
+
seq = seq. subseq(10,DATA.size)
|
110
|
+
seq.pos=OFFSET
|
111
|
+
return seq
|
112
|
+
end
|
113
|
+
end
|
114
|
+
class Reversed <Indexed
|
115
|
+
def a_seq
|
116
|
+
seq =DATA.reverse.to_sequence.reversed
|
117
|
+
seq.pos=12
|
118
|
+
seq
|
119
|
+
end
|
120
|
+
end
|
121
|
+
class Circular <Indexed
|
122
|
+
def a_seq
|
123
|
+
seq = Sequence::Circular.new(super,OFFSET)
|
124
|
+
end
|
125
|
+
undef_method(:test_nearbegin, :test_nearend)
|
126
|
+
def absolutes_always_fail; true end
|
127
|
+
def randlimit; DATA.size end
|
128
|
+
end
|
129
|
+
nil&& #disabled for now.... too many size dependancies in tests
|
130
|
+
class Big <Indexed
|
131
|
+
def a_seq
|
132
|
+
seq = Sequence::Indexed.new(DATA.gsub(/[ \n]/,' '*1000+"\\1"))
|
133
|
+
seq.move(OFFSET+2000)
|
134
|
+
return seq
|
135
|
+
end
|
136
|
+
undef_method :test_pos
|
137
|
+
end
|
138
|
+
class Tempfile <Indexed
|
139
|
+
@@seq =nil
|
140
|
+
@@count=0
|
141
|
+
def a_seq
|
142
|
+
@@seq and @@seq.data.close(true)
|
143
|
+
|
144
|
+
tf=::Tempfile.new("test_seq#@@count"); @@count+=1
|
145
|
+
|
146
|
+
tf.write DATA
|
147
|
+
|
148
|
+
tf.pos=OFFSET
|
149
|
+
@@seq = Sequence::File.new tf
|
150
|
+
@@seq.goto OFFSET
|
151
|
+
@@seq
|
152
|
+
end
|
153
|
+
undef_method(:test_insert,:test_delete,:test_modify,:test_insert_empty,:test_delete_empty,:test_insert_start,:test_delete_start,:test_insert_end,:test_delete_end,:test_randomized_methods_some_more)
|
154
|
+
undef_method :test_modify_and_read_joints, :test_pos_munging
|
155
|
+
undef_method :test_write_and_read_joints, :test_insert_and_read_joints, :test_delete_and_read_joint
|
156
|
+
end
|
157
|
+
|
158
|
+
class List < Indexed
|
159
|
+
def a_seq
|
160
|
+
|
161
|
+
seq = Sequence::List.new(DATA.scan(/.{1,8}/m).map{|str| str.to_sequence})
|
162
|
+
seq.pos=OFFSET
|
163
|
+
seq
|
164
|
+
end
|
165
|
+
|
166
|
+
def test__lookup_idx
|
167
|
+
seq=a_seq
|
168
|
+
(0..DATA.size).map{|i|
|
169
|
+
assert_equal i/8, seq._lookup_idx(i)
|
170
|
+
}
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
class ListMaxxed < Indexed
|
176
|
+
def a_seq
|
177
|
+
|
178
|
+
seq = Sequence::List.new(DATA.scan(/./m).map{|str| str.to_sequence})
|
179
|
+
seq.pos=OFFSET
|
180
|
+
seq
|
181
|
+
end
|
182
|
+
def test__lookup_idx
|
183
|
+
seq=a_seq
|
184
|
+
(0...DATA.size).map{|i|
|
185
|
+
assert_equal i, seq._lookup_idx(i)
|
186
|
+
}
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
class List1 < Indexed
|
191
|
+
def a_seq
|
192
|
+
|
193
|
+
seq = Sequence::List.new([DATA.dup.to_sequence])
|
194
|
+
seq.pos=OFFSET
|
195
|
+
seq
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
class List2 < Indexed
|
200
|
+
def a_seq
|
201
|
+
mid=DATA.size/2
|
202
|
+
seq = Sequence::List.new(
|
203
|
+
[DATA[0...mid].to_sequence,
|
204
|
+
DATA[mid..-1].to_sequence]
|
205
|
+
)
|
206
|
+
seq.pos=OFFSET
|
207
|
+
seq
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
class ListRandomized < Indexed
|
212
|
+
def a_seq
|
213
|
+
maxchunk=DATA.size/5
|
214
|
+
idx=0
|
215
|
+
list=[]
|
216
|
+
begin
|
217
|
+
len=rand(maxchunk)+1
|
218
|
+
list<<DATA[idx,len].to_sequence
|
219
|
+
idx+=len
|
220
|
+
|
221
|
+
end until(idx>=DATA.size)
|
222
|
+
|
223
|
+
seq= Sequence::List.new(list)
|
224
|
+
seq.pos=OFFSET
|
225
|
+
seq
|
226
|
+
|
227
|
+
|
228
|
+
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
class IO < Indexed
|
233
|
+
def a_seq
|
234
|
+
r,w=::IO.pipe
|
235
|
+
r=Sequence::IO[r]
|
236
|
+
w.write DATA
|
237
|
+
r.read(OFFSET)== DATA[0,OFFSET] or raise "predata mismatch inside pipe"
|
238
|
+
return r
|
239
|
+
end
|
240
|
+
|
241
|
+
#need to disable tests that move cursor position back or modify data
|
242
|
+
undef_method(*(MOVEPOSMETHODS+MODIFYMETHODS))
|
243
|
+
end
|
244
|
+
|
245
|
+
|
246
|
+
module SmallScanBuffered
|
247
|
+
SequenceTests.constants.each{|k|
|
248
|
+
xk= SequenceTests.const_get(k)
|
249
|
+
next unless (xk.is_a? Class and xk<=Indexed)
|
250
|
+
const_set k, xk=Class.new(xk)
|
251
|
+
xk.instance_eval do
|
252
|
+
define_method :a_seq do
|
253
|
+
result=super
|
254
|
+
result.maxmatchlen=6
|
255
|
+
result
|
256
|
+
end
|
257
|
+
end
|
258
|
+
}
|
259
|
+
end
|
260
|
+
|
261
|
+
=begin disabled for now; too many failures
|
262
|
+
module Buffered
|
263
|
+
SequenceTests.constants.each{|k|
|
264
|
+
oxk= SequenceTests.const_get(k)
|
265
|
+
next unless (oxk<=Indexed rescue nil)
|
266
|
+
const_set k, xk=Class.new(SequenceTests::Indexed)
|
267
|
+
xk.instance_eval do
|
268
|
+
define_method :a_seq do
|
269
|
+
#p [::Sequence::Buffered, oxk]
|
270
|
+
::Sequence::Buffered.new(oxk.allocate.a_seq)
|
271
|
+
end
|
272
|
+
end
|
273
|
+
}
|
274
|
+
end
|
275
|
+
=end
|
276
|
+
|
277
|
+
module Shifting
|
278
|
+
SequenceTests.constants.each{|k|
|
279
|
+
oxk= SequenceTests.const_get(k)
|
280
|
+
next unless Class===oxk
|
281
|
+
const_set k, xk=Class.new(SequenceTests::Indexed)
|
282
|
+
xk.instance_eval do
|
283
|
+
define_method :a_seq do
|
284
|
+
#p [::Sequence::Shifting, oxk]
|
285
|
+
::Sequence::Shifting.new(oxk.allocate.a_seq)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
}
|
289
|
+
end
|
290
|
+
|
291
|
+
class Indexed
|
292
|
+
RANDOMIZED_METHODS=[:test_slice,:test_insert,:test_delete,:test_modify]
|
293
|
+
undef test_randomized_methods_some_more
|
294
|
+
def test_randomized_methods_some_more n=50
|
295
|
+
RANDOMIZED_METHODS.each{|m| n.times{send m}}
|
296
|
+
end
|
297
|
+
|
298
|
+
def rand_pos_pair
|
299
|
+
[rand(randlimit),rand(randlimit)].sort
|
300
|
+
end
|
301
|
+
|
302
|
+
def randlimit
|
303
|
+
DATA.size+1
|
304
|
+
end
|
305
|
+
|
306
|
+
|
307
|
+
undef_method(*(MOVEPOSMETHODS+MODIFYMETHODS))
|
308
|
+
def test_pos_munging
|
309
|
+
(1..3).each{|n|
|
310
|
+
seq=a_seq
|
311
|
+
assert_equal OFFSET, seq.pos
|
312
|
+
seq[seq.pos-4,seq.pos+4]="oook"*n
|
313
|
+
assert_equal OFFSET-4, seq.pos
|
314
|
+
}
|
315
|
+
|
316
|
+
end
|
317
|
+
|
318
|
+
def test_slice_empty; test_slice 0,0 end
|
319
|
+
|
320
|
+
def test_slice first=nil, last=nil
|
321
|
+
seq =a_seq
|
322
|
+
|
323
|
+
first or (first,last=*rand_pos_pair)
|
324
|
+
|
325
|
+
assert_equal DATA[first...last], seq[first...last]
|
326
|
+
assert_equal DATA[first..last], seq[first..last]
|
327
|
+
assert_equal DATA[first,last-first], seq[first,last-first]
|
328
|
+
assert_equal DATA[first..last], seq[first..last]
|
329
|
+
assert_equal DATA[first], seq[first]
|
330
|
+
|
331
|
+
assert_equal( (DATA.slice first...last), (seq.slice first...last) )
|
332
|
+
assert_equal( (DATA.slice first..last), (seq.slice first..last) )
|
333
|
+
assert_equal( (DATA.slice first,last-first), (seq.slice first,last-first) )
|
334
|
+
assert_equal( (DATA.slice first..last), (seq.slice first..last) )
|
335
|
+
assert_equal( (DATA.slice first), (seq.slice first) )
|
336
|
+
end
|
337
|
+
|
338
|
+
|
339
|
+
|
340
|
+
|
341
|
+
def test_size
|
342
|
+
assert_equal DATA.size, a_seq.size
|
343
|
+
end
|
344
|
+
|
345
|
+
def test_read
|
346
|
+
seq =a_seq
|
347
|
+
assert_equal 'that t', (seq.read 6)
|
348
|
+
assert_equal OFFSET+6, seq.pos
|
349
|
+
end
|
350
|
+
|
351
|
+
def test_readahead
|
352
|
+
seq =a_seq
|
353
|
+
assert_equal 'that t', (seq.readahead 6)
|
354
|
+
assert_equal OFFSET, seq.pos
|
355
|
+
end
|
356
|
+
|
357
|
+
def test_pos
|
358
|
+
seq =a_seq
|
359
|
+
assert_equal OFFSET, seq.pos
|
360
|
+
end
|
361
|
+
|
362
|
+
def test_pos=
|
363
|
+
seq =a_seq
|
364
|
+
assert_equal OFFSET, seq.pos
|
365
|
+
seq.pos=25
|
366
|
+
assert_equal 25, seq.pos
|
367
|
+
assert_equal 'y talk', (seq.read 6)
|
368
|
+
assert_equal 31, seq.pos
|
369
|
+
end
|
370
|
+
|
371
|
+
def test_nearbegin
|
372
|
+
seq =a_seq
|
373
|
+
seq.pos=5
|
374
|
+
assert seq.nearbegin(10)
|
375
|
+
assert ! seq.nearbegin(4)
|
376
|
+
end
|
377
|
+
|
378
|
+
def test_nearend
|
379
|
+
seq =a_seq
|
380
|
+
seq.pos=-5
|
381
|
+
assert seq.nearend(10)
|
382
|
+
assert ! seq.nearend(4)
|
383
|
+
end
|
384
|
+
|
385
|
+
def test_write
|
386
|
+
seq =a_seq
|
387
|
+
assert_equal 17, seq.write("gooblesnortembopy")
|
388
|
+
assert_equal OFFSET+17, seq.pos
|
389
|
+
seq.pos=OFFSET
|
390
|
+
assert_equal "gooblesnortembopy", (seq.read 17)
|
391
|
+
assert_raises(ArgumentError) { seq.write("gooblesnortembopy"*10) }
|
392
|
+
end
|
393
|
+
|
394
|
+
def test_write_and_read_joints
|
395
|
+
table=[[:write,+5], [:writeahead,+0], [:writeback,-0.1], [:writebehind,-5]]
|
396
|
+
table.each do|(mname,offs)|
|
397
|
+
seq =a_seq
|
398
|
+
offs<0 and offs=-offs and seq.move 5
|
399
|
+
assert_equal 5, seq.send( mname, ("snark") )
|
400
|
+
assert_equal OFFSET+offs.to_i, seq.pos
|
401
|
+
# seq.pos=OFFSET
|
402
|
+
assert_equal "baz sn", seq[OFFSET-4,6]
|
403
|
+
assert_equal "rktoug", seq[OFFSET+3,6]
|
404
|
+
assert_equal OFFSET+offs.to_i, seq.pos
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
def test_modify_and_read_joints
|
409
|
+
seq =a_seq
|
410
|
+
# seq.pos+=2
|
411
|
+
assert_equal OFFSET, seq.pos
|
412
|
+
assert_equal "snark", seq.modify(15..25,"snark")
|
413
|
+
assert_equal OFFSET, seq.pos
|
414
|
+
# seq.pos=OFFSET
|
415
|
+
assert_equal "thasna", seq[12,6]
|
416
|
+
assert_equal "rk tal", seq[18,6]
|
417
|
+
end
|
418
|
+
|
419
|
+
|
420
|
+
def test_insert_and_read_joints
|
421
|
+
seq =a_seq
|
422
|
+
assert_equal "snark", seq.insert(seq.pos,"snark")
|
423
|
+
assert_equal OFFSET, seq.pos
|
424
|
+
# seq.pos=OFFSET
|
425
|
+
assert_equal "baz sn", seq[OFFSET-4,6]
|
426
|
+
assert_equal "rkthat", seq[OFFSET+3,6]
|
427
|
+
assert_equal OFFSET, seq.pos
|
428
|
+
assert_equal "snark", seq.read(5)
|
429
|
+
assert_equal OFFSET+5, seq.pos
|
430
|
+
end
|
431
|
+
|
432
|
+
def test_delete_and_read_joint
|
433
|
+
seq =a_seq
|
434
|
+
assert_equal nil, seq.delete(seq.pos,5)
|
435
|
+
assert_equal OFFSET, seq.pos
|
436
|
+
# seq.pos=OFFSET
|
437
|
+
assert_equal "baz to", seq[OFFSET-4,6]
|
438
|
+
assert_equal OFFSET, seq.pos
|
439
|
+
assert_equal "tough", seq.read(5)
|
440
|
+
assert_equal OFFSET+5, seq.pos
|
441
|
+
end
|
442
|
+
|
443
|
+
def test_writeback
|
444
|
+
seq =a_seq
|
445
|
+
assert_equal 6, seq.writeback("gooble")
|
446
|
+
assert_equal OFFSET-6, seq.pos
|
447
|
+
seq.pos=OFFSET
|
448
|
+
assert_equal "gooble", (seq.readback 6)
|
449
|
+
assert_raises(ArgumentError) { seq.writeback("gooblesnortembopy") }
|
450
|
+
end
|
451
|
+
|
452
|
+
def change_notification(seq,first,oldlen,newlen)
|
453
|
+
assert_same @seq, seq
|
454
|
+
assert_equal @first, first
|
455
|
+
assert_equal @oldlen, oldlen
|
456
|
+
assert_equal @newlen, newlen
|
457
|
+
@changes_seen +=1
|
458
|
+
end
|
459
|
+
|
460
|
+
def add_test_listener(seq,first,last,newlen)
|
461
|
+
@changes_seen=0
|
462
|
+
if first<0
|
463
|
+
first+=seq.size
|
464
|
+
last.zero? and last=seq.size
|
465
|
+
end
|
466
|
+
last<0 and last+=seq.size
|
467
|
+
@seq,@first,@oldlen,@newlen= seq,first,last-first,newlen
|
468
|
+
seq.on_change_notify(self)
|
469
|
+
end
|
470
|
+
|
471
|
+
def verify_test_listener expect_count=1
|
472
|
+
assert_equal @seq.instance_eval{@change_listeners}.to_a, [self]
|
473
|
+
if expect_count!=@changes_seen
|
474
|
+
assert_equal @seq.instance_eval{@change_listeners}.to_a, [self]
|
475
|
+
assert false
|
476
|
+
end
|
477
|
+
assert_equal @seq.instance_eval{@change_listeners}.to_a, [self]
|
478
|
+
end
|
479
|
+
|
480
|
+
def test_insert_empty; test_insert 15,15 end
|
481
|
+
def test_insert_start; test_insert 0,15 end
|
482
|
+
def test_insert_end; test_insert( -15,0 ) end
|
483
|
+
|
484
|
+
def test_insert(first=nil,last=nil)
|
485
|
+
seq =a_seq
|
486
|
+
first or (first,last=*rand_pos_pair)
|
487
|
+
# puts("first=#{first}, last=#{last}")
|
488
|
+
len=last-first
|
489
|
+
add_test_listener seq,first,first,len
|
490
|
+
assert_equal seq.instance_eval{@change_listeners}.to_a, [self]
|
491
|
+
seq.insert first, " "*len
|
492
|
+
assert_equal seq.instance_eval{@change_listeners}.to_a, [self]
|
493
|
+
verify_test_listener(1)
|
494
|
+
end
|
495
|
+
|
496
|
+
|
497
|
+
def test_delete_empty; test_delete 15,15 end
|
498
|
+
def test_delete_start; test_delete 0,15 end
|
499
|
+
def test_delete_end; test_delete( -15,0 ) end
|
500
|
+
|
501
|
+
|
502
|
+
def test_delete first=nil,last=nil
|
503
|
+
seq =a_seq
|
504
|
+
first or (first,last=*rand_pos_pair)
|
505
|
+
# puts "first=#{first}, last=#{last}"
|
506
|
+
len=last-first
|
507
|
+
add_test_listener seq,first,last,0
|
508
|
+
list=seq.instance_eval{@change_listeners}.to_a
|
509
|
+
assert_equal 1, list.size
|
510
|
+
assert_equal self.__id__, list.first.__id__
|
511
|
+
seq.delete first, len
|
512
|
+
assert_equal 1, list.size
|
513
|
+
assert_equal self.__id__, list.first.__id__
|
514
|
+
verify_test_listener(1)
|
515
|
+
end
|
516
|
+
|
517
|
+
|
518
|
+
def test_modify
|
519
|
+
seq =a_seq
|
520
|
+
first,last=*rand_pos_pair
|
521
|
+
oldlen=last-first
|
522
|
+
newlen=rand(2*DATA.size)
|
523
|
+
add_test_listener seq,first,last,newlen
|
524
|
+
#puts "first: #{first}, oldlen: #{oldlen}, newlen: #{newlen}"
|
525
|
+
assert_equal seq.instance_eval{@change_listeners}.to_a, [self]
|
526
|
+
seq.modify first, oldlen," "*newlen
|
527
|
+
assert_equal seq.instance_eval{@change_listeners}.to_a, [self]
|
528
|
+
verify_test_listener(1)
|
529
|
+
end
|
530
|
+
|
531
|
+
|
532
|
+
def verify_failmatch_status(meth,pat,pos=nil)
|
533
|
+
_=(seq =a_seq).send meth,pat
|
534
|
+
pos ? seq.pos=pos : pos=OFFSET
|
535
|
+
assert_equal nil, _
|
536
|
+
assert_equal pos, seq.pos
|
537
|
+
assert seq.last_match.nil?
|
538
|
+
end
|
539
|
+
|
540
|
+
def verify_aftermatch_status(seq,pos,matches,starts,pre,post,eof)
|
541
|
+
assert_equal pos, seq.pos
|
542
|
+
assert seq.last_match
|
543
|
+
i=nil
|
544
|
+
matches.each_with_index{|m,i|
|
545
|
+
assert_equal m, seq.last_match[i]
|
546
|
+
}
|
547
|
+
assert_equal nil, seq.last_match[i+1]
|
548
|
+
assert_equal matches.length, seq.last_match.length
|
549
|
+
assert_equal matches, seq.last_match.to_a
|
550
|
+
starts.each_with_index{|start,i|
|
551
|
+
assert_equal start, seq.last_match.begin(i)
|
552
|
+
assert_equal start+matches[i].size, seq.last_match.end(i)
|
553
|
+
|
554
|
+
assert_equal start, seq.last_match.offset(i).first
|
555
|
+
assert_equal start+matches[i].size, seq.last_match.offset(i).last
|
556
|
+
}
|
557
|
+
assert_equal nil, seq.last_match.begin(i+1)
|
558
|
+
assert_equal nil, seq.last_match.end(i+1)
|
559
|
+
assert_equal nil, seq.last_match.offset(i+1)
|
560
|
+
|
561
|
+
assert_equal pre, seq.last_match.pre_match[0..-1]
|
562
|
+
assert_equal post, seq.last_match.post_match[0..-1]
|
563
|
+
eof and assert seq.last_match.post_match.eof?
|
564
|
+
end
|
565
|
+
|
566
|
+
def verify_scan_methods(rex,offset,matchstr,restargs,backwards=false)
|
567
|
+
mappings={
|
568
|
+
:scan=>[:to_s,1], :check =>[:to_s,0],
|
569
|
+
:skip=>[:size,1], :match? =>[:size,0],
|
570
|
+
|
571
|
+
|
572
|
+
|
573
|
+
:scan_until=>[:to_s,1], :check_until=>[:to_s,0],
|
574
|
+
:skip_until=>[:size,1], :exist? =>[:size,0],
|
575
|
+
}
|
576
|
+
|
577
|
+
mappings.each{|k,v|
|
578
|
+
k=k.to_s.sub(/(_until|\?)?$/) {"back"+$1} if backwards
|
579
|
+
seq =a_seq
|
580
|
+
seq.pos=offset
|
581
|
+
assert_equal matchstr.send( v[0]), seq.send( k, rex)
|
582
|
+
factor=v[1]
|
583
|
+
factor=-factor if backwards
|
584
|
+
verify_aftermatch_status(seq,
|
585
|
+
offset+matchstr.size*factor, *restargs
|
586
|
+
)
|
587
|
+
}
|
588
|
+
end
|
589
|
+
|
590
|
+
def verify_scan_until_methods rex,offset,prematch,matchstr,restargs
|
591
|
+
restargs[1][0]==offset and return verify_scan_methods( rex,offset,matchstr,restargs )
|
592
|
+
mappings={
|
593
|
+
:scan_until=>[:to_s,1],
|
594
|
+
:check_until=>[:to_s,0],
|
595
|
+
:skip_until=>[:size,1],
|
596
|
+
:exist? =>[:size,0]
|
597
|
+
}
|
598
|
+
|
599
|
+
mappings.each{|k,v|
|
600
|
+
|
601
|
+
(seq =a_seq)
|
602
|
+
seq.pos=offset
|
603
|
+
assert_equal prematch.send(v[0])+matchstr.send(v[0]), seq.send( k, rex)
|
604
|
+
verify_aftermatch_status( seq,offset+(prematch.size+matchstr.size)*v[1],*restargs )
|
605
|
+
}
|
606
|
+
|
607
|
+
|
608
|
+
%w[scan skip check match?].each{|meth|
|
609
|
+
verify_failmatch_status( meth,rex,offset )
|
610
|
+
}
|
611
|
+
end
|
612
|
+
|
613
|
+
def test_scanning
|
614
|
+
|
615
|
+
assert_equal "that ", a_seq.readahead(5)
|
616
|
+
|
617
|
+
verify_scan_methods( /th(is|at)/,OFFSET,"that",
|
618
|
+
[%W[that at],[OFFSET,OFFSET+2],
|
619
|
+
"", " tough guy talk\ndon't make you a dog", false] )
|
620
|
+
=begin
|
621
|
+
_=(seq =a_seq).scan /th(is|at)/
|
622
|
+
assert_equal "that", _
|
623
|
+
verify_aftermatch_status(
|
624
|
+
seq,16,%W[that at],[OFFSET,OFFSET+2],
|
625
|
+
"", " tough guy talk\ndon't make you a dog", false
|
626
|
+
)
|
627
|
+
|
628
|
+
_=(seq =a_seq).check /th(is|at)/
|
629
|
+
assert_equal "that", _
|
630
|
+
verify_aftermatch_status(
|
631
|
+
seq,12,%W[that at],[OFFSET,OFFSET+2],
|
632
|
+
"", " tough guy talk\ndon't make you a dog", false
|
633
|
+
)
|
634
|
+
|
635
|
+
_=(seq =a_seq).skip /th(is|at)/
|
636
|
+
assert_equal 4, _
|
637
|
+
verify_aftermatch_status(
|
638
|
+
seq,16,%W[that at],[OFFSET,OFFSET+2],
|
639
|
+
"", " tough guy talk\ndon't make you a dog", false
|
640
|
+
)
|
641
|
+
|
642
|
+
_=(seq =a_seq).match? /th(is|at)/
|
643
|
+
assert_equal 4, _
|
644
|
+
verify_aftermatch_status(
|
645
|
+
seq,12,%W[that at],[OFFSET,OFFSET+2],
|
646
|
+
"", " tough guy talk\ndon't make you a dog", false
|
647
|
+
)
|
648
|
+
=end
|
649
|
+
|
650
|
+
verify_scan_until_methods( /[mb]ake/, OFFSET, "that tough guy talk\ndon't ", "make",
|
651
|
+
[%W[make],[OFFSET+26],
|
652
|
+
"that tough guy talk\ndon't "," you a dog", false] )
|
653
|
+
|
654
|
+
=begin
|
655
|
+
_=(seq =a_seq).scan_until /[mb]ake/
|
656
|
+
assert_equal "that tough guy talk\ndon't make", _
|
657
|
+
verify_aftermatch_status(
|
658
|
+
seq,16+26,%W[make],[OFFSET+26],
|
659
|
+
"that tough guy talk\ndon't "," you a dog", false
|
660
|
+
)
|
661
|
+
|
662
|
+
_=(seq =a_seq).check_until /[mb]ake/
|
663
|
+
assert_equal "that tough guy talk\ndon't make", _
|
664
|
+
verify_aftermatch_status(
|
665
|
+
seq,OFFSET,%W[make],[OFFSET+26],
|
666
|
+
"that tough guy talk\ndon't "," you a dog", false
|
667
|
+
)
|
668
|
+
|
669
|
+
_=(seq =a_seq).skip_until /[mb]ake/
|
670
|
+
assert_equal 30, _
|
671
|
+
verify_aftermatch_status(
|
672
|
+
seq,16+26,%W[make],[OFFSET+26],
|
673
|
+
"that tough guy talk\ndon't "," you a dog", false
|
674
|
+
)
|
675
|
+
|
676
|
+
_=(seq =a_seq).exist? /[mb]ake/
|
677
|
+
assert_equal 30, _
|
678
|
+
verify_aftermatch_status(
|
679
|
+
seq,OFFSET,%W[make],[OFFSET+26],
|
680
|
+
"that tough guy talk\ndon't "," you a dog", false
|
681
|
+
)
|
682
|
+
=end
|
683
|
+
|
684
|
+
#ok, and now with anchors
|
685
|
+
verify_failmatch_status :scan_until, /[cr]at\Z/
|
686
|
+
verify_failmatch_status :scan_until, /you\Z/
|
687
|
+
verify_failmatch_status :scan_until, /talk\Z/
|
688
|
+
|
689
|
+
verify_failmatch_status :exist?, /[cr]at\Z/
|
690
|
+
verify_failmatch_status :exist?, /you\Z/
|
691
|
+
verify_failmatch_status :exist?, /talk\Z/
|
692
|
+
|
693
|
+
verify_failmatch_status :check_until, /[cr]at\Z/
|
694
|
+
verify_failmatch_status :check_until, /you\Z/
|
695
|
+
verify_failmatch_status :check_until, /talk\Z/
|
696
|
+
|
697
|
+
verify_failmatch_status :skip_until, /[cr]at\Z/
|
698
|
+
verify_failmatch_status :skip_until, /you\Z/
|
699
|
+
verify_failmatch_status :skip_until, /talk\Z/
|
700
|
+
|
701
|
+
unless absolutes_always_fail
|
702
|
+
verify_scan_until_methods( /(d([^d]+))\Z/,OFFSET,"", "that tough guy talk\ndon't make you a dog",
|
703
|
+
[%W[dog dog og],[OFFSET+37,OFFSET+37,OFFSET+38],"that tough guy talk\ndon't make you a ", "", true] )
|
704
|
+
|
705
|
+
=begin
|
706
|
+
_=(seq =a_seq).scan_until /(d([^d]+))\Z/
|
707
|
+
assert_equal "that tough guy talk\ndon't make you a dog", _
|
708
|
+
verify_aftermatch_status(
|
709
|
+
seq,52,%W[dog dog og],[49,49,50],
|
710
|
+
"that tough guy talk\ndon't make you a ","", true
|
711
|
+
)
|
712
|
+
|
713
|
+
_=(seq =a_seq).exist? /(d([^d]+))\Z/
|
714
|
+
assert_equal 40, _
|
715
|
+
verify_aftermatch_status(
|
716
|
+
seq,OFFSET,%W[dog dog og],[49,49,50],
|
717
|
+
"that tough guy talk\ndon't make you a ","", true
|
718
|
+
)
|
719
|
+
|
720
|
+
_=(seq =a_seq).check_until /(d([^d]+))\Z/
|
721
|
+
assert_equal "that tough guy talk\ndon't make you a dog", _
|
722
|
+
verify_aftermatch_status(
|
723
|
+
seq,12,%W[dog dog og],[49,49,50],
|
724
|
+
"that tough guy talk\ndon't make you a ","", true
|
725
|
+
)
|
726
|
+
|
727
|
+
_=(seq =a_seq).skip_until /(d([^d]+))\Z/
|
728
|
+
assert_equal 40, _
|
729
|
+
verify_aftermatch_status(
|
730
|
+
seq,52,%W[dog dog og],[49,49,50],
|
731
|
+
"that tough guy talk\ndon't make you a ","", true
|
732
|
+
)
|
733
|
+
=end
|
734
|
+
end
|
735
|
+
|
736
|
+
#implicitly anchored with anchors
|
737
|
+
verify_failmatch_status :scan, /[cr]at\Z/,49
|
738
|
+
verify_failmatch_status :scan, /you\Z/,43
|
739
|
+
verify_failmatch_status :scan, /talk\Z/,31
|
740
|
+
|
741
|
+
verify_failmatch_status :check, /[cr]at\Z/,49
|
742
|
+
verify_failmatch_status :check, /you\Z/,43
|
743
|
+
verify_failmatch_status :check, /talk\Z/,31
|
744
|
+
|
745
|
+
verify_failmatch_status :skip, /[cr]at\Z/,49
|
746
|
+
verify_failmatch_status :skip, /you\Z/,43
|
747
|
+
verify_failmatch_status :skip, /talk\Z/,31
|
748
|
+
|
749
|
+
verify_failmatch_status :exist?, /[cr]at\Z/,49
|
750
|
+
verify_failmatch_status :exist?, /you\Z/,43
|
751
|
+
verify_failmatch_status :exist?, /talk\Z/,31
|
752
|
+
|
753
|
+
unless absolutes_always_fail
|
754
|
+
verify_scan_methods( /(d([^d]+))\Z/,OFFSET+37, "dog",
|
755
|
+
[%W[dog dog og],[OFFSET+37,OFFSET+37,OFFSET+38],"", "", true] )
|
756
|
+
|
757
|
+
|
758
|
+
=begin
|
759
|
+
_=(seq =a_seq)
|
760
|
+
seq.pos=49 #at 'dog'
|
761
|
+
_= seq.scan /(d([^d]+))\Z/
|
762
|
+
assert_equal "dog", _
|
763
|
+
verify_aftermatch_status(
|
764
|
+
seq,52,%W[dog dog og],[49,49,50],"","", true
|
765
|
+
)
|
766
|
+
|
767
|
+
_=(seq =a_seq)
|
768
|
+
seq.pos=49 #at 'dog'
|
769
|
+
_= seq.match? /(d([^d]+))\Z/
|
770
|
+
assert_equal 3, _
|
771
|
+
verify_aftermatch_status(
|
772
|
+
seq,49,%W[dog dog og],[49,49,50],"","", true
|
773
|
+
)
|
774
|
+
|
775
|
+
_=(seq =a_seq)
|
776
|
+
seq.pos=49 #at 'dog'
|
777
|
+
_= seq.check /(d([^d]+))\Z/
|
778
|
+
assert_equal "dog", _
|
779
|
+
verify_aftermatch_status(
|
780
|
+
seq,49,%W[dog dog og],[49,49,50],"","", true
|
781
|
+
)
|
782
|
+
|
783
|
+
_=(seq =a_seq)
|
784
|
+
seq.pos=49 #at 'dog'
|
785
|
+
_= seq.skip /(d([^d]+))\Z/
|
786
|
+
assert_equal 3, _
|
787
|
+
verify_aftermatch_status(
|
788
|
+
seq,52,%W[dog dog og],[49,49,50],"","", true
|
789
|
+
)
|
790
|
+
=end
|
791
|
+
end
|
792
|
+
#$ as anchor
|
793
|
+
verify_failmatch_status :scan_until, /[cr]at$/
|
794
|
+
verify_failmatch_status :scan_until, /you$/
|
795
|
+
|
796
|
+
verify_failmatch_status :exist?, /[cr]at$/
|
797
|
+
verify_failmatch_status :exist?, /you$/
|
798
|
+
|
799
|
+
verify_failmatch_status :check_until, /[cr]at$/
|
800
|
+
verify_failmatch_status :check_until, /you$/
|
801
|
+
|
802
|
+
verify_failmatch_status :skip_until, /[cr]at$/
|
803
|
+
verify_failmatch_status :skip_until, /you$/
|
804
|
+
|
805
|
+
unless absolutes_always_fail
|
806
|
+
verify_scan_until_methods( /(d([^d]+))$/,OFFSET,"", "that tough guy talk\ndon't make you a dog",
|
807
|
+
[%W[dog dog og],[OFFSET+37,OFFSET+37,OFFSET+38],"that tough guy talk\ndon't make you a ", "", true] )
|
808
|
+
|
809
|
+
|
810
|
+
=begin
|
811
|
+
_=(seq =a_seq).scan_until /(d([^d]+))$/
|
812
|
+
assert_equal "that tough guy talk\ndon't make you a dog", _
|
813
|
+
verify_aftermatch_status(
|
814
|
+
seq,52,%W[dog dog og],[49,49,50],
|
815
|
+
"that tough guy talk\ndon't make you a ","", true
|
816
|
+
)
|
817
|
+
|
818
|
+
_=(seq =a_seq).exist? /(d([^d]+))$/
|
819
|
+
assert_equal 40, _
|
820
|
+
verify_aftermatch_status(
|
821
|
+
seq,OFFSET,%W[dog dog og],[49,49,50],
|
822
|
+
"that tough guy talk\ndon't make you a ","", true
|
823
|
+
)
|
824
|
+
|
825
|
+
_=(seq =a_seq).check_until /(d([^d]+))$/
|
826
|
+
assert_equal "that tough guy talk\ndon't make you a dog", _
|
827
|
+
verify_aftermatch_status(
|
828
|
+
seq,12,%W[dog dog og],[49,49,50],
|
829
|
+
"that tough guy talk\ndon't make you a ","", true
|
830
|
+
)
|
831
|
+
|
832
|
+
_=(seq =a_seq).skip_until /(d([^d]+))$/
|
833
|
+
assert_equal 40, _
|
834
|
+
verify_aftermatch_status(
|
835
|
+
seq,52,%W[dog dog og],[49,49,50],
|
836
|
+
"that tough guy talk\ndon't make you a ","", true
|
837
|
+
)
|
838
|
+
=end
|
839
|
+
end
|
840
|
+
|
841
|
+
verify_scan_until_methods( /(st|[bt])alk$/,OFFSET,"", "that tough guy talk",
|
842
|
+
[%W[talk t],[OFFSET+15,OFFSET+15],"that tough guy ","\ndon't make you a dog", false] )
|
843
|
+
=begin
|
844
|
+
_=(seq =a_seq).scan_until /(st|[bt])alk$/
|
845
|
+
assert_equal "that tough guy talk", _
|
846
|
+
verify_aftermatch_status(seq,31,%W[talk t],[27,27],"that tough guy ","\ndon't make you a dog",false)
|
847
|
+
|
848
|
+
_=(seq =a_seq).exist? /(st|[bt])alk$/
|
849
|
+
assert_equal 19, _
|
850
|
+
verify_aftermatch_status(seq,12,%W[talk t],[27,27],"that tough guy ","\ndon't make you a dog",false)
|
851
|
+
|
852
|
+
_=(seq =a_seq).check_until /(st|[bt])alk$/
|
853
|
+
assert_equal "that tough guy talk", _
|
854
|
+
verify_aftermatch_status(seq,12,%W[talk t],[27,27],"that tough guy ","\ndon't make you a dog",false)
|
855
|
+
|
856
|
+
_=(seq =a_seq).skip_until /(st|[bt])alk$/
|
857
|
+
assert_equal 19, _
|
858
|
+
verify_aftermatch_status(seq,31,%W[talk t],[27,27],"that tough guy ","\ndon't make you a dog",false)
|
859
|
+
=end
|
860
|
+
verify_failmatch_status :scan_until, /(bob|talk\Z|(dou(gh)?))/
|
861
|
+
verify_failmatch_status :check_until, /(bob|talk\Z|(dou(gh)?))/
|
862
|
+
verify_failmatch_status :skip_until, /(bob|talk\Z|(dou(gh)?))/
|
863
|
+
verify_failmatch_status :exist?, /(bob|talk\Z|(dou(gh)?))/
|
864
|
+
|
865
|
+
verify_scan_until_methods( /(bob|you\Z|(tou(gh)?))/,OFFSET, "", "that tough",
|
866
|
+
[%W[tough tough tough gh],[OFFSET+5,OFFSET+5,OFFSET+5,OFFSET+8],"that "," guy talk\ndon't make you a dog", false] )
|
867
|
+
|
868
|
+
_=(seq =a_seq).scan_until( /(bob|you\Z|(tou(gh)?))/ )
|
869
|
+
assert_equal "that tough", _
|
870
|
+
verify_aftermatch_status(seq,22,%W[tough tough tough gh],[17,17,17,20],"that "," guy talk\ndon't make you a dog",false)
|
871
|
+
|
872
|
+
_=(seq =a_seq).check_until( /(bob|you\Z|(tou(gh)?))/ )
|
873
|
+
assert_equal "that tough", _
|
874
|
+
verify_aftermatch_status(seq,12,%W[tough tough tough gh],[17,17,17,20],"that "," guy talk\ndon't make you a dog",false)
|
875
|
+
|
876
|
+
|
877
|
+
_=(seq =a_seq).skip_until( /(bob|you\Z|(tou(gh)?))/ )
|
878
|
+
assert_equal 10, _
|
879
|
+
verify_aftermatch_status(seq,22,%W[tough tough tough gh],[17,17,17,20],"that "," guy talk\ndon't make you a dog",false)
|
880
|
+
|
881
|
+
|
882
|
+
_=(seq =a_seq).exist?( /(bob|you\Z|(tou(gh)?))/ )
|
883
|
+
assert_equal 10, _
|
884
|
+
verify_aftermatch_status(seq,12,%W[tough tough tough gh],[17,17,17,20],"that "," guy talk\ndon't make you a dog",false)
|
885
|
+
|
886
|
+
|
887
|
+
|
888
|
+
|
889
|
+
|
890
|
+
seq =a_seq
|
891
|
+
_=seq.scanback( /baz $/ )
|
892
|
+
assert_equal "baz ",_
|
893
|
+
verify_aftermatch_status(seq,8,["baz "],[8],"foo\nbar ","",false)
|
894
|
+
end
|
895
|
+
end
|
896
|
+
end
|
897
|
+
|
898
|
+
|
899
|
+
|