3 # Check ->defer and ->flush methods
5 # This is the old version, which you used in the past when
6 # there was a defer buffer separate from the read cache.
7 # There isn't any longer.
11 my $file = "tf$$.txt";
12 $: = Tie::File::_default_recsep();
13 my $data = "rec0$:rec1$:rec2$:";
20 print "ok $N\n"; $N++;
22 open F, "> $file" or die $!;
26 $o = tie @a, 'Tie::File', $file;
27 print $o ? "ok $N\n" : "not ok $N\n";
30 # (3-6) Deferred storage
33 check_contents($data); # nothing written yet
35 check_contents($data); # nothing written yet
39 check_contents($data . "rec3$:rec4$:"); # now it's written
41 # (9-12) Deferred writing disabled?
43 check_contents("${data}rec9$:rec4$:");
45 check_contents("${data}rec9$:rec8$:");
47 # (13-18) Now let's try two batches of records
51 check_contents($data); # nothing written yet
53 check_contents($data); # nothing written yet
55 check_contents("record0$:rec1$:record2$:");
57 # (19-22) Deferred writing past the end of the file
60 check_contents("record0$:rec1$:record2$:");
62 check_contents("record0$:rec1$:record2$:$:record4$:");
65 # (23-26) Now two long batches
70 check_contents("record0$:rec1$:record2$:$:record4$:");
72 check_contents(join $:, "r0".."r2", "", "r4".."r6", "");
74 # (27-30) Now let's make sure that discarded writes are really discarded
75 # We have a 2Mib buffer here, so we can be sure that we aren't accidentally
79 $a[$_] = "discarded$_";
81 check_contents(join $:, "r0".."r2", "", "r4".."r6", "");
83 check_contents(join $:, "r0".."r2", "", "r4".."r6", "");
85 ################################################################
87 # Now we're going to test the results of a small memory limit
91 $data = join "$:", map("record$_", 0..7), ""; # records are 8 or 9 bytes long
92 open F, "> $file" or die $!;
97 # Limit cache+buffer size to 47 bytes
99 # -- that's enough space for 5 records, but not 6, on both \n and \r\n systems
101 # -- that's enough space for 2 records, but not 3, on both \n and \r\n systems
102 $o = tie @a, 'Tie::File', $file, memory => $MAX, dw_size => $BUF;
103 print $o ? "ok $N\n" : "not ok $N\n";
106 # (31-32) Fill up the read cache
109 # the cache now contains records 3,4,5,6,7.
110 check_caches({map(($_ => "record$_$:"), 3..7)},
113 # (33-44) See if overloading the defer starts by flushing the read cache
114 # and then flushes out the defer
116 $a[0] = "recordA"; # That should flush record 3 from the cache
117 check_caches({map(($_ => "record$_$:"), 4..7)},
119 check_contents($data);
121 $a[1] = "recordB"; # That should flush record 4 from the cache
122 check_caches({map(($_ => "record$_$:"), 5..7)},
125 check_contents($data);
127 $a[2] = "recordC"; # That should flush the whole darn defer
128 # This shouldn't change the cache contents
129 check_caches({map(($_ => "record$_$:"), 5..7)},
131 check_contents(join("$:", qw(recordA recordB recordC
132 record3 record4 record5 record6 record7)) . "$:");
134 $a[3] = "recordD"; # even though we flushed, deferring is STILL ENABLED
135 check_caches({map(($_ => "record$_$:"), 5..7)},
137 check_contents(join("$:", qw(recordA recordB recordC
138 record3 record4 record5 record6 record7)) . "$:");
140 # Check readcache-deferbuffer interactions
142 # (45-47) This should remove outdated data from the read cache
144 check_caches({6 => "record6$:", 7 => "record7$:"},
145 {3 => "recordD$:", 5 => "recordE$:"});
146 check_contents(join("$:", qw(recordA recordB recordC
147 record3 record4 record5 record6 record7)) . "$:");
149 # (48-51) This should read back out of the defer buffer
150 # without adding anything to the read cache
153 print $z eq "recordE" ? "ok $N\n" : "not ok $N\n"; $N++;
154 check_caches({6 => "record6$:", 7 => "record7$:"},
155 {3 => "recordD$:", 5 => "recordE$:"});
156 check_contents(join("$:", qw(recordA recordB recordC
157 record3 record4 record5 record6 record7)) . "$:");
159 # (52-55) This should repopulate the read cache with a new record
161 print $z eq "recordA" ? "ok $N\n" : "not ok $N\n"; $N++;
162 check_caches({0 => "recordA$:", 6 => "record6$:", 7 => "record7$:"},
163 {3 => "recordD$:", 5 => "recordE$:"});
164 check_contents(join("$:", qw(recordA recordB recordC
165 record3 record4 record5 record6 record7)) . "$:");
167 # (56-59) This should flush the LRU record from the read cache
169 print $z eq "record4" ? "ok $N\n" : "not ok $N\n"; $N++;
170 check_caches({7 => "record7$:", 0 => "recordA$:", 4 => "record4$:"},
171 {3 => "recordD$:", 5 => "recordE$:"});
172 check_contents(join("$:", qw(recordA recordB recordC
173 record3 record4 record5 record6 record7)) . "$:");
175 # (60-63) This should FLUSH the deferred buffer
176 $z = splice @a, 3, 1, "recordZ";
177 print $z eq "recordD" ? "ok $N\n" : "not ok $N\n"; $N++;
178 check_caches({7 => "record7$:", 0 => "recordA$:", 4 => "record4$:", 3 => "recordZ$:"},
180 check_contents(join("$:", qw(recordA recordB recordC
181 recordZ record4 recordE record6 record7)) . "$:");
183 # (64-66) We should STILL be in deferred writing mode
185 check_caches({7 => "record7$:", 0 => "recordA$:", 4 => "record4$:", 3 => "recordZ$:"},
187 check_contents(join("$:", qw(recordA recordB recordC
188 recordZ record4 recordE record6 record7)) . "$:");
190 # Fill up the defer buffer again
192 # (67-69) This should OVERWRITE the existing deferred record
193 # and NOT flush the buffer
195 check_caches({7 => "record7$:", 0 => "recordA$:", 3 => "recordZ$:"},
196 {5 => "recordQ$:", 4 => "recordP$:"});
197 check_contents(join("$:", qw(recordA recordB recordC
198 recordZ record4 recordE record6 record7)) . "$:");
200 # (70-72) Discard should just dump the whole deferbuffer
202 check_caches({7 => "record7$:", 0 => "recordA$:", 3 => "recordZ$:"},
204 check_contents(join("$:", qw(recordA recordB recordC
205 recordZ record4 recordE record6 record7)) . "$:");
207 # (73-75) NOW we are out of deferred writing mode
209 check_caches({7 => "record7$:", 0 => "recordF$:", 3 => "recordZ$:"},
211 check_contents(join("$:", qw(recordF recordB recordC
212 recordZ record4 recordE record6 record7)) . "$:");
214 # (76-79) Last call--untying the array should flush the deferbuffer
217 check_caches({7 => "record7$:", 3 => "recordZ$:"},
218 {0 => "flushed$:" });
219 check_contents(join("$:", qw(recordF recordB recordC
220 recordZ record4 recordE record6 record7)) . "$:");
223 # (79) We can't use check_contents any more, because the object is dead
224 open F, "< $file" or die;
226 { local $/ ; $z = <F> }
228 my $x = join("$:", qw(flushed recordB recordC
229 recordZ record4 recordE record6 record7)) . "$:";
233 my $msg = ctrlfix("expected <$x>, got <$z>");
234 print "not ok $N \# $msg\n";
238 ################################################################
242 my ($xcache, $xdefer) = @_;
244 # my $integrity = $o->_check_integrity($file, $ENV{INTEGRITY});
245 # print $integrity ? "ok $N\n" : "not ok $N\n";
250 # Copy the contents of the cache into a regular hash
252 for my $k ($o->{cache}->ckeys) {
253 $cache{$k} = $o->{cache}->_produce($k);
256 $good &&= hash_equal(\%cache, $xcache, "true cache", "expected cache");
257 $good &&= hash_equal($o->{deferred}, $xdefer, "true defer", "expected defer");
258 print $good ? "ok $N\n" : "not ok $N\n";
263 my ($a, $b, $ha, $hb) = @_;
264 $ha = 'first hash' unless defined $ha;
265 $hb = 'second hash' unless defined $hb;
270 for my $k (keys %$a) {
271 if (! exists $b->{$k}) {
272 print ctrlfix("# Key $k is in $ha but not $hb"), "\n";
274 } elsif ($b->{$k} ne $a->{$k}) {
275 print ctrlfix("# Key $k is <$a->{$k}> in $ha but <$b->{$k}> in $hb"), "\n";
283 for my $k (keys %$b) {
284 unless ($b_seen{$k}) {
285 print ctrlfix("# Key $k is in $hb but not $ha"), "\n";
297 my $integrity = $o->_check_integrity($file, $ENV{INTEGRITY});
298 print $integrity ? "ok $N\n" : "not ok $N\n";
301 local *FH = $o->{fh};
302 seek FH, 0, SEEK_SET;
305 { local $/; $a = <FH> }
306 $a = "" unless defined $a;
310 my $msg = ctrlfix("# expected <$x>, got <$a>");
311 print "not ok $N\n$msg\n";
326 1 while unlink $file;