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