1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6#
7# Check behavior of 'autodefer' feature
8# Mostly this isn't implemented yet
9# This file is primarily here to make sure that the promised ->autodefer
10# method doesn't croak.
11#
12
13use POSIX 'SEEK_SET';
14
15my $file = "tf31-$$.txt";
16$: = Tie::File::_default_recsep();
17my $data = "rec0$:rec1$:rec2$:";
18my ($o, $n, @a);
19
20print "1..65\n";
21
22my $N = 1;
23use Tie::File;
24print "ok $N\n"; $N++;
25
26open F, '>', $file or die $!;
27binmode F;
28print F $data;
29close F;
30$o = tie @a, 'Tie::File', $file;
31print $o ? "ok $N\n" : "not ok $N\n";
32$N++;
33
34# I am an undocumented feature
35$o->{autodefer_filelen_threshhold} = 0;
36# Normally autodeferring only works on large files.  This disables that.
37
38# (3-22) Deferred storage
39$a[3] = "rec3";
40check_autodeferring('OFF');
41$a[4] = "rec4";
42check_autodeferring('OFF');
43$a[5] = "rec5";
44check_autodeferring('ON');
45check_contents($data . "rec3$:rec4$:"); # only the first two were written
46$a[6] = "rec6";
47check_autodeferring('ON');
48check_contents($data . "rec3$:rec4$:"); # still nothing written
49$a[7] = "rec7";
50check_autodeferring('ON');
51check_contents($data . "rec3$:rec4$:"); # still nothing written
52$a[0] = "recX";
53check_autodeferring('OFF');
54check_contents("recX$:rec1$:rec2$:rec3$:rec4$:rec5$:rec6$:rec7$:");
55$a[1] = "recY";
56check_autodeferring('OFF');
57check_contents("recX$:recY$:rec2$:rec3$:rec4$:rec5$:rec6$:rec7$:");
58$a[2] = "recZ";                 # it kicks in here
59check_autodeferring('ON');
60check_contents("recX$:recY$:rec2$:rec3$:rec4$:rec5$:rec6$:rec7$:");
61
62# (23-26) Explicitly enabling deferred writing deactivates autodeferring
63$o->defer;
64check_autodeferring('OFF');
65check_contents("recX$:recY$:recZ$:rec3$:rec4$:rec5$:rec6$:rec7$:");
66$o->discard;
67check_autodeferring('OFF');
68
69# (27-32) Now let's try the CLEAR special case
70@a = ("r0" .. "r4");
71check_autodeferring('ON');
72# The file was extended to the right length, but nothing was actually written.
73check_contents("$:$:$:$:$:");
74$a[2] = "fish";
75check_autodeferring('OFF');
76check_contents("r0$:r1$:fish$:r3$:r4$:");
77
78# (33-47) Now let's try the originally intended application:  a 'for' loop.
79my $it = 0;
80for (@a) {
81  $_ = "##$_";
82  if ($it == 0) {
83    check_autodeferring('OFF');
84    check_contents("##r0$:r1$:fish$:r3$:r4$:");
85  } elsif ($it == 1) {
86    check_autodeferring('OFF');
87    check_contents("##r0$:##r1$:fish$:r3$:r4$:");
88  } else {
89    check_autodeferring('ON');
90    check_contents("##r0$:##r1$:fish$:r3$:r4$:");
91  }
92  $it++;
93}
94
95# (48-56) Autodeferring should not become active during explicit defer mode
96$o->defer();  # This should flush the pending autodeferred records
97              # and deactivate autodeferring
98check_autodeferring('OFF');
99check_contents("##r0$:##r1$:##fish$:##r3$:##r4$:");
100@a = ("s0" .. "s4");
101check_autodeferring('OFF');
102check_contents("");
103$o->flush;
104check_autodeferring('OFF');
105check_contents("s0$:s1$:s2$:s3$:s4$:");
106
107undef $o; untie @a;
108
109# Limit cache+buffer size to 47 bytes 
110my $MAX = 47;
111#  -- that's enough space for 5 records, but not 6, on both \n and \r\n systems
112my $BUF = 20;
113#  -- that's enough space for 2 records, but not 3, on both \n and \r\n systems
114# Re-tie the object for more tests
115$o = tie @a, 'Tie::File', $file, autodefer => 0;
116die $! unless $o;
117# I am an undocumented feature
118$o->{autodefer_filelen_threshhold} = 0;
119# Normally autodeferring only works on large files.  This disables that.
120
121# (57-59) Did the autodefer => 0 option work?
122# (If it doesn't, a whole bunch of the other test files will fail.)
123@a = (0..3);
124check_autodeferring('OFF');
125check_contents(join("$:", qw(0 1 2 3), ""));
126
127# (60-62) Does the ->autodefer method work?
128$o->autodefer(1);
129@a = (10..13);
130check_autodeferring('ON');
131check_contents("$:$:$:$:");  # This might be unfortunate.
132
133# (63-65) Does the ->autodefer method work?
134$o->autodefer(0);
135check_autodeferring('OFF');
136check_contents(join("$:", qw(10 11 12 13), ""));
137
138
139sub check_autodeferring {
140  my ($x) = shift;
141  my $a = $o->{autodeferring} ? 'ON' : 'OFF';
142  if ($x eq $a) {
143    print "ok $N\n";
144  } else {
145    print "not ok $N \# Autodeferring was $a, expected it to be $x\n";
146  }
147  $N++;
148}
149
150
151sub check_contents {
152  my $x = shift;
153#  for (values %{$o->{cache}}) {
154#    print "# cache=$_";    
155#  }
156  
157  my $integrity = $o->_check_integrity($file, $ENV{INTEGRITY});
158  local *FH = $o->{fh};
159  seek FH, 0, SEEK_SET;
160  print $integrity ? "ok $N\n" : "not ok $N\n";
161  $N++;
162  my $a;
163  { local $/; $a = <FH> }
164  $a = "" unless defined $a;
165  if ($a eq $x) {
166    print "ok $N\n";
167  } else {
168    ctrlfix(my $msg = "# expected <$x>, got <$a>");
169    print "not ok $N\n$msg\n";
170  }
171  $N++;
172}
173
174sub ctrlfix {
175  for (@_) {
176    s/\n/\\n/g;
177    s/\r/\\r/g;
178  }
179}
180
181END {
182  undef $o;
183  untie @a;
184  1 while unlink $file;
185}
186
187