1#!/usr/bin/perl
2#
3# Check SPLICE function's effect on the file
4# (07_rv_splice.t checks its return value)
5#
6# Each call to 'check_contents' actually performs two tests.
7# First, it calls the tied object's own 'check_integrity' method,
8# which makes sure that the contents of the read cache and offset tables
9# accurately reflect the contents of the file.
10# Then, it checks the actual contents of the file against the expected
11# contents.
12
13use strict;
14use warnings;
15
16use POSIX 'SEEK_SET';
17
18my $file = "tf10-$$.txt";
19my $data = "rec0blahrec1blahrec2blah";
20
21print "1..101\n";
22
23my $N = 1;
24use Tie::File;
25print "ok $N\n"; $N++;  # partial credit just for showing up
26
27init_file($data);
28
29my @a;
30my $o = tie @a, 'Tie::File', $file, recsep => 'blah';
31print $o ? "ok $N\n" : "not ok $N\n";
32$N++;
33
34my $n;
35
36# (3-22) splicing at the beginning
37splice(@a, 0, 0, "rec4");
38check_contents("rec4blah$data");
39splice(@a, 0, 1, "rec5");       # same length
40check_contents("rec5blah$data");
41splice(@a, 0, 1, "record5");    # longer
42check_contents("record5blah$data");
43
44splice(@a, 0, 1, "r5");         # shorter
45check_contents("r5blah$data");
46splice(@a, 0, 1);               # removal
47check_contents("$data");
48splice(@a, 0, 0);               # no-op
49check_contents("$data");
50splice(@a, 0, 0, 'r7', 'rec8'); # insert more than one
51check_contents("r7blahrec8blah$data");
52splice(@a, 0, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
53check_contents("rec7blahrecord8blahrec9blah$data");
54
55splice(@a, 0, 3, 'record9', 'rec10'); # delete more than insert
56check_contents("record9blahrec10blah$data");
57splice(@a, 0, 2);               # delete more than one
58check_contents("$data");
59
60
61# (23-42) splicing in the middle
62splice(@a, 1, 0, "rec4");
63check_contents("rec0blahrec4blahrec1blahrec2blah");
64splice(@a, 1, 1, "rec5");       # same length
65check_contents("rec0blahrec5blahrec1blahrec2blah");
66splice(@a, 1, 1, "record5");    # longer
67check_contents("rec0blahrecord5blahrec1blahrec2blah");
68
69splice(@a, 1, 1, "r5");         # shorter
70check_contents("rec0blahr5blahrec1blahrec2blah");
71splice(@a, 1, 1);               # removal
72check_contents("$data");
73splice(@a, 1, 0);               # no-op
74check_contents("$data");
75splice(@a, 1, 0, 'r7', 'rec8'); # insert more than one
76check_contents("rec0blahr7blahrec8blahrec1blahrec2blah");
77splice(@a, 1, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
78check_contents("rec0blahrec7blahrecord8blahrec9blahrec1blahrec2blah");
79
80splice(@a, 1, 3, 'record9', 'rec10'); # delete more than insert
81check_contents("rec0blahrecord9blahrec10blahrec1blahrec2blah");
82splice(@a, 1, 2);               # delete more than one
83check_contents("$data");
84
85# (43-62) splicing at the end
86splice(@a, 3, 0, "rec4");
87check_contents("$ {data}rec4blah");
88splice(@a, 3, 1, "rec5");       # same length
89check_contents("$ {data}rec5blah");
90splice(@a, 3, 1, "record5");    # longer
91check_contents("$ {data}record5blah");
92
93splice(@a, 3, 1, "r5");         # shorter
94check_contents("$ {data}r5blah");
95splice(@a, 3, 1);               # removal
96check_contents("$data");
97splice(@a, 3, 0);               # no-op
98check_contents("$data");
99splice(@a, 3, 0, 'r7', 'rec8'); # insert more than one
100check_contents("$ {data}r7blahrec8blah");
101splice(@a, 3, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
102check_contents("$ {data}rec7blahrecord8blahrec9blah");
103
104splice(@a, 3, 3, 'record9', 'rec10'); # delete more than insert
105check_contents("$ {data}record9blahrec10blah");
106splice(@a, 3, 2);               # delete more than one
107check_contents("$data");
108
109# (63-82) splicing with negative subscript
110splice(@a, -1, 0, "rec4");
111check_contents("rec0blahrec1blahrec4blahrec2blah");
112splice(@a, -1, 1, "rec5");       # same length
113check_contents("rec0blahrec1blahrec4blahrec5blah");
114splice(@a, -1, 1, "record5");    # longer
115check_contents("rec0blahrec1blahrec4blahrecord5blah");
116
117splice(@a, -1, 1, "r5");         # shorter
118check_contents("rec0blahrec1blahrec4blahr5blah");
119splice(@a, -1, 1);               # removal
120check_contents("rec0blahrec1blahrec4blah");
121splice(@a, -1, 0);               # no-op
122check_contents("rec0blahrec1blahrec4blah");
123splice(@a, -1, 0, 'r7', 'rec8'); # insert more than one
124check_contents("rec0blahrec1blahr7blahrec8blahrec4blah");
125splice(@a, -1, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
126check_contents("rec0blahrec1blahr7blahrec8blahrec7blahrecord8blahrec9blah");
127
128splice(@a, -3, 3, 'record9', 'rec10'); # delete more than insert
129check_contents("rec0blahrec1blahr7blahrec8blahrecord9blahrec10blah");
130splice(@a, -4, 3);               # delete more than one
131check_contents("rec0blahrec1blahrec10blah");
132
133# (83-84) scrub it all out
134splice(@a, 0, 3);
135check_contents("");
136
137# (85-86) put some back in
138splice(@a, 0, 0, "rec0", "rec1");
139check_contents("rec0blahrec1blah");
140
141# (87-88) what if we remove too many records?
142splice(@a, 0, 17);
143check_contents("");
144
145# (89-92) In the past, splicing past the end was not correctly detected
146# (0.14)
147splice(@a, 89, 3);
148check_contents("");
149splice(@a, @a, 3);
150check_contents("");
151
152# (93-96) Also we did not emulate splice's freaky behavior when inserting
153# past the end of the array (1.14)
154splice(@a, 89, 0, "I", "like", "pie");
155check_contents("Iblahlikeblahpieblah");
156splice(@a, 89, 0, "pie pie pie");
157check_contents("Iblahlikeblahpieblahpie pie pieblah");
158
159# (97) Splicing with too large a negative number should be fatal
160# This test ignored because it causes 5.6.1 and 5.7.3 to dump core
161# It also garbles the stack under 5.005_03 (20020401)
162# NOT MY FAULT
163if ($] > 5.007003) {
164  eval { splice(@a, -7, 0) };
165  print $@ =~ /^Modification of non-creatable array value attempted, subscript -7/
166      ? "ok $N\n" : "not ok $N \# \$\@ was '$@'\n";
167} else {
168  print "ok $N \# skipped (versions through 5.7.3 dump core here.)\n";
169}
170$N++;
171
172# (98-101) Test default arguments
173splice @a, 0, 0, (0..11);
174splice @a, 4;
175check_contents("0blah1blah2blah3blah");
176splice @a;
177check_contents("");
178
179
180sub init_file {
181  my $data = shift;
182  open F, '>', $file or die $!;
183  binmode F;
184  print F $data;
185  close F;
186}
187
188sub check_contents {
189  my $x = shift;
190  my $integrity = $o->_check_integrity($file, $ENV{INTEGRITY});
191  print $integrity ? "ok $N\n" : "not ok $N\n";
192  $N++;
193  local *FH = $o->{fh};
194  seek FH, 0, SEEK_SET;
195  my $a;
196  { local $/; $a = <FH> }
197  $a = "" unless defined $a;
198  if ($a eq $x) {
199    print "ok $N\n";
200  } else {
201    ctrlfix(my $msg = "# expected <$x>, got <$a>");
202    print "not ok $N\n$msg\n";
203  }
204  $N++;
205}
206
207sub ctrlfix {
208  for (@_) {
209    s/\n/\\n/g;
210    s/\r/\\r/g;
211  }
212}
213
214END {
215  undef $o;
216  untie @a;
217  1 while unlink $file;
218}
219
220