sequence 0.1.0

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