sequence 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|