summaryrefslogtreecommitdiff
path: root/lib/Tie/File
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Tie/File')
-rw-r--r--lib/Tie/File/01_gen.t89
-rw-r--r--lib/Tie/File/02_fetchsize.t47
-rw-r--r--lib/Tie/File/03_longfetch.t38
-rw-r--r--lib/Tie/File/04_splice.t163
-rw-r--r--lib/Tie/File/05_size.t78
-rw-r--r--lib/Tie/File/06_fixrec.t36
-rw-r--r--lib/Tie/File/07_rv_splice.t157
-rw-r--r--lib/Tie/File/08_ro.t41
-rw-r--r--lib/Tie/File/09_gen_rs.t90
-rw-r--r--lib/Tie/File/10_splice_rs.t162
-rw-r--r--lib/Tie/File/11_rv_splice_rs.t157
-rw-r--r--lib/Tie/File/12_longfetch_rs.t38
-rw-r--r--lib/Tie/File/13_size_rs.t78
13 files changed, 1174 insertions, 0 deletions
diff --git a/lib/Tie/File/01_gen.t b/lib/Tie/File/01_gen.t
new file mode 100644
index 0000000000..58c7a9732c
--- /dev/null
+++ b/lib/Tie/File/01_gen.t
@@ -0,0 +1,89 @@
+#!/usr/bin/perl
+
+my $file = "tf$$.txt";
+
+print "1..38\n";
+
+my $N = 1;
+use Tie::File;
+print "ok $N\n"; $N++;
+
+my $o = tie @a, 'Tie::File', $file;
+print $o ? "ok $N\n" : "not ok $N\n";
+$N++;
+
+# 3-4 create
+$a[0] = 'rec0';
+check_contents("rec0");
+
+# 5-8 append
+$a[1] = 'rec1';
+check_contents("rec0", "rec1");
+$a[2] = 'rec2';
+check_contents("rec0", "rec1", "rec2");
+
+# 9-14 same-length alterations
+$a[0] = 'new0';
+check_contents("new0", "rec1", "rec2");
+$a[1] = 'new1';
+check_contents("new0", "new1", "rec2");
+$a[2] = 'new2';
+check_contents("new0", "new1", "new2");
+
+# 15-24 lengthening alterations
+$a[0] = 'long0';
+check_contents("long0", "new1", "new2");
+$a[1] = 'long1';
+check_contents("long0", "long1", "new2");
+$a[2] = 'long2';
+check_contents("long0", "long1", "long2");
+$a[1] = 'longer1';
+check_contents("long0", "longer1", "long2");
+$a[0] = 'longer0';
+check_contents("longer0", "longer1", "long2");
+
+# 25-34 shortening alterations, including truncation
+$a[0] = 'short0';
+check_contents("short0", "longer1", "long2");
+$a[1] = 'short1';
+check_contents("short0", "short1", "long2");
+$a[2] = 'short2';
+check_contents("short0", "short1", "short2");
+$a[1] = 'sh1';
+check_contents("short0", "sh1", "short2");
+$a[0] = 'sh0';
+check_contents("sh0", "sh1", "short2");
+
+# file with holes
+$a[4] = 'rec4';
+check_contents("sh0", "sh1", "short2", "", "rec4");
+$a[3] = 'rec3';
+check_contents("sh0", "sh1", "short2", "rec3", "rec4");
+
+
+# try inserting a record into the middle of an empty file
+
+
+sub check_contents {
+ my @c = @_;
+ my $x = join $/, @c, '';
+ local *FH;
+ my $open = open FH, "< $file";
+ my $a;
+ { local $/; $a = <FH> }
+ print (($open && $a eq $x) ? "ok $N\n" : "not ok $N # file @c\n");
+ $N++;
+
+ # now check FETCH:
+ my $good = 1;
+ for (0.. $#c) {
+ $good = 0 unless $a[$_] eq "$c[$_]\n";
+ }
+ print (($open && $good) ? "ok $N\n" : "not ok $N # fetch @c\n");
+ $N++;
+}
+
+END {
+ 1 while unlink $file;
+}
+
diff --git a/lib/Tie/File/02_fetchsize.t b/lib/Tie/File/02_fetchsize.t
new file mode 100644
index 0000000000..aaf44f09c7
--- /dev/null
+++ b/lib/Tie/File/02_fetchsize.t
@@ -0,0 +1,47 @@
+#!/usr/bin/perl
+
+my $file = "tf$$.txt";
+my $data = "rec1$/rec2$/rec3$/";
+
+print "1..6\n";
+
+my $N = 1;
+use Tie::File;
+print "ok $N\n"; $N++;
+
+open F, "> $file" or die $!;
+print F $data;
+close F;
+
+
+my $o = tie @a, 'Tie::File', $file;
+print $o ? "ok $N\n" : "not ok $N\n";
+$N++;
+
+my $n;
+
+# 3 test array element count
+$n = @a;
+print $n == 3 ? "ok $N\n" : "not ok $N # n=$n\n";
+$N++;
+
+# 4 same thing again
+$n = @a;
+print $n == 3 ? "ok $N\n" : "not ok $N # n=$n\n";
+$N++;
+
+# 5 test $#a notation
+$n = $#a;
+print $n == 2 ? "ok $N\n" : "not ok $N # n=$n\n";
+$N++;
+
+# 6 test looping over array elements
+my $q;
+for (@a) { $q .= $_ }
+print $q eq $data ? "ok $N\n" : "not ok $N # n=$n\n";
+$N++;
+
+END {
+ 1 while unlink $file;
+}
+
diff --git a/lib/Tie/File/03_longfetch.t b/lib/Tie/File/03_longfetch.t
new file mode 100644
index 0000000000..7e36962e9b
--- /dev/null
+++ b/lib/Tie/File/03_longfetch.t
@@ -0,0 +1,38 @@
+#!/usr/bin/perl
+#
+# Make sure we can fetch a record in the middle of the file
+# before we've ever looked at any records before it
+#
+# (tests _fill_offsets_to() )
+#
+
+my $file = "tf$$.txt";
+my $data = "rec0$/rec1$/rec2$/";
+
+print "1..5\n";
+
+my $N = 1;
+use Tie::File;
+print "ok $N\n"; $N++;
+
+open F, "> $file" or die $!;
+print F $data;
+close F;
+
+
+my $o = tie @a, 'Tie::File', $file;
+print $o ? "ok $N\n" : "not ok $N\n";
+$N++;
+
+my $n;
+
+# 3-5
+for (2, 1, 0) {
+ print $a[$_] eq "rec$_$/" ? "ok $N\n" : "not ok $N # rec=$a[$_] ?\n";
+ $N++;
+}
+
+END {
+ 1 while unlink $file;
+}
+
diff --git a/lib/Tie/File/04_splice.t b/lib/Tie/File/04_splice.t
new file mode 100644
index 0000000000..c8daf0e9e3
--- /dev/null
+++ b/lib/Tie/File/04_splice.t
@@ -0,0 +1,163 @@
+#!/usr/bin/perl
+#
+# Check SPLICE function's effect on the file
+# (07_rv_splice.t checks its return value)
+#
+# Each call to 'check_contents' actually performs two tests.
+# First, it calls the tied object's own 'check_integrity' method,
+# which makes sure that the contents of the read cache and offset tables
+# accurately reflect the contents of the file.
+# Then, it checks the actual contents of the file against the expected
+# contents.
+
+use lib '/home/mjd/src/perl/Tie-File2/lib';
+my $file = "tf$$.txt";
+my $data = "rec0$/rec1$/rec2$/";
+
+print "1..88\n";
+
+my $N = 1;
+use Tie::File;
+print "ok $N\n"; $N++; # partial credit just for showing up
+
+my $o = tie @a, 'Tie::File', $file;
+print $o ? "ok $N\n" : "not ok $N\n";
+$N++;
+
+my $n;
+
+# (3-22) splicing at the beginning
+init_file($data);
+
+splice(@a, 0, 0, "rec4");
+check_contents("rec4$/$data");
+splice(@a, 0, 1, "rec5"); # same length
+check_contents("rec5$/$data");
+splice(@a, 0, 1, "record5"); # longer
+check_contents("record5$/$data");
+
+splice(@a, 0, 1, "r5"); # shorter
+check_contents("r5$/$data");
+splice(@a, 0, 1); # removal
+check_contents("$data");
+splice(@a, 0, 0); # no-op
+check_contents("$data");
+splice(@a, 0, 0, 'r7', 'rec8'); # insert more than one
+check_contents("r7$/rec8$/$data");
+splice(@a, 0, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
+check_contents("rec7$/record8$/rec9$/$data");
+
+splice(@a, 0, 3, 'record9', 'rec10'); # delete more than insert
+check_contents("record9$/rec10$/$data");
+splice(@a, 0, 2); # delete more than one
+check_contents("$data");
+
+
+# (23-42) splicing in the middle
+splice(@a, 1, 0, "rec4");
+check_contents("rec0$/rec4$/rec1$/rec2$/");
+splice(@a, 1, 1, "rec5"); # same length
+check_contents("rec0$/rec5$/rec1$/rec2$/");
+splice(@a, 1, 1, "record5"); # longer
+check_contents("rec0$/record5$/rec1$/rec2$/");
+
+splice(@a, 1, 1, "r5"); # shorter
+check_contents("rec0$/r5$/rec1$/rec2$/");
+splice(@a, 1, 1); # removal
+check_contents("$data");
+splice(@a, 1, 0); # no-op
+check_contents("$data");
+splice(@a, 1, 0, 'r7', 'rec8'); # insert more than one
+check_contents("rec0$/r7$/rec8$/rec1$/rec2$/");
+splice(@a, 1, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
+check_contents("rec0$/rec7$/record8$/rec9$/rec1$/rec2$/");
+
+splice(@a, 1, 3, 'record9', 'rec10'); # delete more than insert
+check_contents("rec0$/record9$/rec10$/rec1$/rec2$/");
+splice(@a, 1, 2); # delete more than one
+check_contents("$data");
+
+# (43-62) splicing at the end
+splice(@a, 3, 0, "rec4");
+check_contents("$ {data}rec4$/");
+splice(@a, 3, 1, "rec5"); # same length
+check_contents("$ {data}rec5$/");
+splice(@a, 3, 1, "record5"); # longer
+check_contents("$ {data}record5$/");
+
+splice(@a, 3, 1, "r5"); # shorter
+check_contents("$ {data}r5$/");
+splice(@a, 3, 1); # removal
+check_contents("$data");
+splice(@a, 3, 0); # no-op
+check_contents("$data");
+splice(@a, 3, 0, 'r7', 'rec8'); # insert more than one
+check_contents("$ {data}r7$/rec8$/");
+splice(@a, 3, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
+check_contents("$ {data}rec7$/record8$/rec9$/");
+
+splice(@a, 3, 3, 'record9', 'rec10'); # delete more than insert
+check_contents("$ {data}record9$/rec10$/");
+splice(@a, 3, 2); # delete more than one
+check_contents("$data");
+
+# (63-82) splicing with negative subscript
+splice(@a, -1, 0, "rec4");
+check_contents("rec0$/rec1$/rec4$/rec2$/");
+splice(@a, -1, 1, "rec5"); # same length
+check_contents("rec0$/rec1$/rec4$/rec5$/");
+splice(@a, -1, 1, "record5"); # longer
+check_contents("rec0$/rec1$/rec4$/record5$/");
+
+splice(@a, -1, 1, "r5"); # shorter
+check_contents("rec0$/rec1$/rec4$/r5$/");
+splice(@a, -1, 1); # removal
+check_contents("rec0$/rec1$/rec4$/");
+splice(@a, -1, 0); # no-op
+check_contents("rec0$/rec1$/rec4$/");
+splice(@a, -1, 0, 'r7', 'rec8'); # insert more than one
+check_contents("rec0$/rec1$/r7$/rec8$/rec4$/");
+splice(@a, -1, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
+check_contents("rec0$/rec1$/r7$/rec8$/rec7$/record8$/rec9$/");
+
+splice(@a, -3, 3, 'record9', 'rec10'); # delete more than insert
+check_contents("rec0$/rec1$/r7$/rec8$/record9$/rec10$/");
+splice(@a, -4, 3); # delete more than one
+check_contents("rec0$/rec1$/rec10$/");
+
+# (83-84) scrub it all out
+splice(@a, 0, 3);
+check_contents("");
+
+# (85-86) put some back in
+splice(@a, 0, 0, "rec0", "rec1");
+check_contents("rec0$/rec1$/");
+
+# (87-88) what if we remove too many records?
+splice(@a, 0, 17);
+check_contents("");
+
+sub init_file {
+ my $data = shift;
+ open F, "> $file" or die $!;
+ print F $data;
+ close F;
+}
+
+sub check_contents {
+ my $x = shift;
+ local *FH;
+ my $integrity = $o->_check_integrity($file, $ENV{INTEGRITY});
+ print $integrity ? "ok $N\n" : "not ok $N\n";
+ $N++;
+ my $open = open FH, "< $file";
+ my $a;
+ { local $/; $a = <FH> }
+ print (($open && $a eq $x) ? "ok $N\n" : "not ok $N\n");
+ $N++;
+}
+
+END {
+ 1 while unlink $file;
+}
+
diff --git a/lib/Tie/File/05_size.t b/lib/Tie/File/05_size.t
new file mode 100644
index 0000000000..4b1085876f
--- /dev/null
+++ b/lib/Tie/File/05_size.t
@@ -0,0 +1,78 @@
+#!/usr/bin/perl
+#
+# Check FETCHSIZE and SETSIZE functions
+# PUSH POP SHIFT UNSHIFT
+#
+
+my $file = "tf$$.txt";
+my $data = "rec0$/rec1$/rec2$/";
+my ($o, $n);
+
+print "1..10\n";
+
+my $N = 1;
+use Tie::File;
+print "ok $N\n"; $N++;
+
+# 2-3 FETCHSIZE 0-length file
+open F, "> $file" or die $!;
+close F;
+$o = tie @a, 'Tie::File', $file;
+print $o ? "ok $N\n" : "not ok $N\n";
+$N++;
+$n = @a;
+print $n == 0 ? "ok $N\n" : "not ok $N # $n, s/b 0\n";
+$N++;
+
+# Reset everything
+undef $o;
+untie @a;
+
+# 4-5 FETCHSIZE positive-length file
+open F, "> $file" or die $!;
+print F $data;
+close F;
+$o = tie @a, 'Tie::File', $file;
+print $o ? "ok $N\n" : "not ok $N\n";
+$N++;
+$n = @a;
+print $n == 3 ? "ok $N\n" : "not ok $N # $n, s/b 0\n";
+$N++;
+
+# STORESIZE
+# 6 Make it longer:
+$#a = 4;
+check_contents("$data$/$/");
+
+# 7 Make it longer again:
+$#a = 6;
+check_contents("$data$/$/$/$/");
+
+# 8 Make it shorter:
+$#a = 4;
+check_contents("$data$/$/");
+
+# 9 Make it shorter again:
+$#a = 2;
+check_contents($data);
+
+# 10 Get rid of it completely:
+$#a = -1;
+check_contents('');
+
+
+sub check_contents {
+ my $x = shift;
+ local *FH;
+ my $open = open FH, "< $file";
+ my $a;
+ { local $/; $a = <FH> }
+ print (($open && $a eq $x) ? "ok $N\n" : "not ok $N\n");
+ $N++;
+}
+
+
+END {
+ 1 while unlink $file;
+}
+
diff --git a/lib/Tie/File/06_fixrec.t b/lib/Tie/File/06_fixrec.t
new file mode 100644
index 0000000000..4a8ceb8d55
--- /dev/null
+++ b/lib/Tie/File/06_fixrec.t
@@ -0,0 +1,36 @@
+#!/usr/bin/perl
+
+my $file = "tf$$.txt";
+
+print "1..5\n";
+
+my $N = 1;
+use Tie::File;
+print "ok $N\n"; $N++;
+
+my $o = tie @a, 'Tie::File', $file;
+print $o ? "ok $N\n" : "not ok $N\n";
+$N++;
+
+$a[0] = 'rec0';
+check_contents("rec0$/");
+$a[1] = "rec1$/";
+check_contents("rec0$/rec1$/");
+$a[2] = "rec2$/$/"; # should we detect this?
+check_contents("rec0$/rec1$/rec2$/$/");
+
+sub check_contents {
+ my $x = shift;
+ local *FH;
+ my $open = open FH, "< $file";
+ my $a;
+ { local $/; $a = <FH> }
+ print (($open && $a eq $x) ? "ok $N\n" : "not ok $N\n");
+ $N++;
+}
+
+
+END {
+ 1 while unlink $file;
+}
+
diff --git a/lib/Tie/File/07_rv_splice.t b/lib/Tie/File/07_rv_splice.t
new file mode 100644
index 0000000000..feaf0096bf
--- /dev/null
+++ b/lib/Tie/File/07_rv_splice.t
@@ -0,0 +1,157 @@
+#!/usr/bin/perl
+#
+# Check SPLICE function's return value
+# (04_splice.t checks its effect on the file)
+#
+
+my $file = "tf$$.txt";
+my $data = "rec0$/rec1$/rec2$/";
+
+print "1..45\n";
+
+my $N = 1;
+use Tie::File;
+print "ok $N\n"; $N++; # partial credit just for showing up
+
+my $o = tie @a, 'Tie::File', $file;
+print $o ? "ok $N\n" : "not ok $N\n";
+$N++;
+
+my $n;
+
+# (3-12) splicing at the beginning
+init_file($data);
+
+@r = splice(@a, 0, 0, "rec4");
+check_result();
+@r = splice(@a, 0, 1, "rec5"); # same length
+check_result("rec4");
+@r = splice(@a, 0, 1, "record5"); # longer
+check_result("rec5");
+
+@r = splice(@a, 0, 1, "r5"); # shorter
+check_result("record5");
+@r = splice(@a, 0, 1); # removal
+check_result("r5");
+@r = splice(@a, 0, 0); # no-op
+check_result();
+@r = splice(@a, 0, 0, 'r7', 'rec8'); # insert more than one
+check_result();
+@r = splice(@a, 0, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
+check_result('r7', 'rec8');
+
+@r = splice(@a, 0, 3, 'record9', 'rec10'); # delete more than insert
+check_result('rec7', 'record8', 'rec9');
+@r = splice(@a, 0, 2); # delete more than one
+check_result('record9', 'rec10');
+
+
+# (13-22) splicing in the middle
+@r = splice(@a, 1, 0, "rec4");
+check_result();
+@r = splice(@a, 1, 1, "rec5"); # same length
+check_result('rec4');
+@r = splice(@a, 1, 1, "record5"); # longer
+check_result('rec5');
+
+@r = splice(@a, 1, 1, "r5"); # shorter
+check_result("record5");
+@r = splice(@a, 1, 1); # removal
+check_result("r5");
+@r = splice(@a, 1, 0); # no-op
+check_result();
+@r = splice(@a, 1, 0, 'r7', 'rec8'); # insert more than one
+check_result();
+@r = splice(@a, 1, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
+check_result('r7', 'rec8');
+
+@r = splice(@a, 1, 3, 'record9', 'rec10'); # delete more than insert
+check_result('rec7', 'record8', 'rec9');
+@r = splice(@a, 1, 2); # delete more than one
+check_result('record9','rec10');
+
+# (23-32) splicing at the end
+@r = splice(@a, 3, 0, "rec4");
+check_result();
+@r = splice(@a, 3, 1, "rec5"); # same length
+check_result('rec4');
+@r = splice(@a, 3, 1, "record5"); # longer
+check_result('rec5');
+
+@r = splice(@a, 3, 1, "r5"); # shorter
+check_result('record5');
+@r = splice(@a, 3, 1); # removal
+check_result('r5');
+@r = splice(@a, 3, 0); # no-op
+check_result();
+@r = splice(@a, 3, 0, 'r7', 'rec8'); # insert more than one
+check_result();
+@r = splice(@a, 3, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
+check_result('r7', 'rec8');
+
+@r = splice(@a, 3, 3, 'record9', 'rec10'); # delete more than insert
+check_result('rec7', 'record8', 'rec9');
+@r = splice(@a, 3, 2); # delete more than one
+check_result('record9', 'rec10');
+
+# (33-42) splicing with negative subscript
+@r = splice(@a, -1, 0, "rec4");
+check_result();
+@r = splice(@a, -1, 1, "rec5"); # same length
+check_result('rec2');
+@r = splice(@a, -1, 1, "record5"); # longer
+check_result("rec5");
+
+@r = splice(@a, -1, 1, "r5"); # shorter
+check_result("record5");
+@r = splice(@a, -1, 1); # removal
+check_result("r5");
+@r = splice(@a, -1, 0); # no-op
+check_result();
+@r = splice(@a, -1, 0, 'r7', 'rec8'); # insert more than one
+check_result();
+@r = splice(@a, -1, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
+check_result('rec4');
+
+@r = splice(@a, -3, 3, 'record9', 'rec10'); # delete more than insert
+check_result('rec7', 'record8', 'rec9');
+@r = splice(@a, -4, 3); # delete more than one
+check_result('r7', 'rec8', 'record9');
+
+# (43) scrub it all out
+@r = splice(@a, 0, 3);
+check_result('rec0', 'rec1', 'rec10');
+
+# (44) put some back in
+@r = splice(@a, 0, 0, "rec0", "rec1");
+check_result();
+
+# (45) what if we remove too many records?
+@r = splice(@a, 0, 17);
+check_result('rec0', 'rec1');
+
+sub init_file {
+ my $data = shift;
+ open F, "> $file" or die $!;
+ print F $data;
+ close F;
+}
+
+# actual results are in @r.
+# expected results are in @_
+sub check_result {
+ my @x = @_;
+ chomp @r;
+ my $good = 1;
+ $good = 0 unless @r == @x;
+ for my $i (0 .. $#r) {
+ $good = 0 unless $r[$i] eq $x[$i];
+ }
+ print $good ? "ok $N\n" : "not ok $N \# was (@r); should be (@x)\n";
+ $N++;
+}
+
+END {
+ 1 while unlink $file;
+}
+
diff --git a/lib/Tie/File/08_ro.t b/lib/Tie/File/08_ro.t
new file mode 100644
index 0000000000..dde7f20f14
--- /dev/null
+++ b/lib/Tie/File/08_ro.t
@@ -0,0 +1,41 @@
+#!/usr/bin/perl
+#
+# Make sure it works to open the file in read-only mode
+#
+
+my $file = "tf$$.txt";
+
+print "1..9\n";
+
+my $N = 1;
+use Tie::File;
+use Fcntl 'O_RDONLY';
+print "ok $N\n"; $N++;
+
+my @items = qw(Gold Frankincense Myrrh Ivory Apes Peacocks);
+init_file(join $/, @items, '');
+
+my $o = tie @a, 'Tie::File', $file, mode => O_RDONLY;
+print $o ? "ok $N\n" : "not ok $N\n";
+$N++;
+
+$#a == $#items ? print "ok $N\n" : print "not ok $N\n";
+$N++;
+
+for my $i (0..$#items) {
+ ("$items[$i]$/" eq $a[$i]) ? print "ok $N\n" : print "not ok $N\n";
+ $N++;
+}
+
+sub init_file {
+ my $data = shift;
+ open F, "> $file" or die $!;
+ print F $data;
+ close F;
+}
+
+
+END {
+ 1 while unlink $file;
+}
+
diff --git a/lib/Tie/File/09_gen_rs.t b/lib/Tie/File/09_gen_rs.t
new file mode 100644
index 0000000000..cf797360e5
--- /dev/null
+++ b/lib/Tie/File/09_gen_rs.t
@@ -0,0 +1,90 @@
+#!/usr/bin/perl
+
+my $file = "tf$$.txt";
+
+print "1..38\n";
+
+my $N = 1;
+use Tie::File;
+print "ok $N\n"; $N++;
+
+my $o = tie @a, 'Tie::File', $file, recsep => 'blah';
+print $o ? "ok $N\n" : "not ok $N\n";
+$N++;
+
+
+# 3-4 create
+$a[0] = 'rec0';
+check_contents("rec0");
+
+# 5-8 append
+$a[1] = 'rec1';
+check_contents("rec0", "rec1");
+$a[2] = 'rec2';
+check_contents("rec0", "rec1", "rec2");
+
+# 9-14 same-length alterations
+$a[0] = 'new0';
+check_contents("new0", "rec1", "rec2");
+$a[1] = 'new1';
+check_contents("new0", "new1", "rec2");
+$a[2] = 'new2';
+check_contents("new0", "new1", "new2");
+
+# 15-24 lengthening alterations
+$a[0] = 'long0';
+check_contents("long0", "new1", "new2");
+$a[1] = 'long1';
+check_contents("long0", "long1", "new2");
+$a[2] = 'long2';
+check_contents("long0", "long1", "long2");
+$a[1] = 'longer1';
+check_contents("long0", "longer1", "long2");
+$a[0] = 'longer0';
+check_contents("longer0", "longer1", "long2");
+
+# 25-34 shortening alterations, including truncation
+$a[0] = 'short0';
+check_contents("short0", "longer1", "long2");
+$a[1] = 'short1';
+check_contents("short0", "short1", "long2");
+$a[2] = 'short2';
+check_contents("short0", "short1", "short2");
+$a[1] = 'sh1';
+check_contents("short0", "sh1", "short2");
+$a[0] = 'sh0';
+check_contents("sh0", "sh1", "short2");
+
+# file with holes
+$a[4] = 'rec4';
+check_contents("sh0", "sh1", "short2", "", "rec4");
+$a[3] = 'rec3';
+check_contents("sh0", "sh1", "short2", "rec3", "rec4");
+
+
+# try inserting a record into the middle of an empty file
+
+
+sub check_contents {
+ my @c = @_;
+ my $x = join 'blah', @c, '';
+ local *FH;
+ my $open = open FH, "< $file";
+ my $a;
+ { local $/; $a = <FH> }
+ print (($open && $a eq $x) ? "ok $N\n" : "not ok $N # file @c\n");
+ $N++;
+
+ # now check FETCH:
+ my $good = 1;
+ for (0.. $#c) {
+ $good = 0 unless $a[$_] eq "$c[$_]blah";
+ }
+ print (($open && $good) ? "ok $N\n" : "not ok $N # fetch @c\n");
+ $N++;
+}
+
+END {
+ 1 while unlink $file;
+}
+
diff --git a/lib/Tie/File/10_splice_rs.t b/lib/Tie/File/10_splice_rs.t
new file mode 100644
index 0000000000..1e1b545ccd
--- /dev/null
+++ b/lib/Tie/File/10_splice_rs.t
@@ -0,0 +1,162 @@
+#!/usr/bin/perl
+#
+# Check SPLICE function's effect on the file
+# (07_rv_splice.t checks its return value)
+#
+# Each call to 'check_contents' actually performs two tests.
+# First, it calls the tied object's own 'check_integrity' method,
+# which makes sure that the contents of the read cache and offset tables
+# accurately reflect the contents of the file.
+# Then, it checks the actual contents of the file against the expected
+# contents.
+
+my $file = "tf$$.txt";
+my $data = "rec0blahrec1blahrec2blah";
+
+print "1..88\n";
+
+my $N = 1;
+use Tie::File;
+print "ok $N\n"; $N++; # partial credit just for showing up
+
+my $o = tie @a, 'Tie::File', $file, recsep => 'blah';
+print $o ? "ok $N\n" : "not ok $N\n";
+$N++;
+
+my $n;
+
+# (3-22) splicing at the beginning
+init_file($data);
+
+splice(@a, 0, 0, "rec4");
+check_contents("rec4blah$data");
+splice(@a, 0, 1, "rec5"); # same length
+check_contents("rec5blah$data");
+splice(@a, 0, 1, "record5"); # longer
+check_contents("record5blah$data");
+
+splice(@a, 0, 1, "r5"); # shorter
+check_contents("r5blah$data");
+splice(@a, 0, 1); # removal
+check_contents("$data");
+splice(@a, 0, 0); # no-op
+check_contents("$data");
+splice(@a, 0, 0, 'r7', 'rec8'); # insert more than one
+check_contents("r7blahrec8blah$data");
+splice(@a, 0, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
+check_contents("rec7blahrecord8blahrec9blah$data");
+
+splice(@a, 0, 3, 'record9', 'rec10'); # delete more than insert
+check_contents("record9blahrec10blah$data");
+splice(@a, 0, 2); # delete more than one
+check_contents("$data");
+
+
+# (23-42) splicing in the middle
+splice(@a, 1, 0, "rec4");
+check_contents("rec0blahrec4blahrec1blahrec2blah");
+splice(@a, 1, 1, "rec5"); # same length
+check_contents("rec0blahrec5blahrec1blahrec2blah");
+splice(@a, 1, 1, "record5"); # longer
+check_contents("rec0blahrecord5blahrec1blahrec2blah");
+
+splice(@a, 1, 1, "r5"); # shorter
+check_contents("rec0blahr5blahrec1blahrec2blah");
+splice(@a, 1, 1); # removal
+check_contents("$data");
+splice(@a, 1, 0); # no-op
+check_contents("$data");
+splice(@a, 1, 0, 'r7', 'rec8'); # insert more than one
+check_contents("rec0blahr7blahrec8blahrec1blahrec2blah");
+splice(@a, 1, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
+check_contents("rec0blahrec7blahrecord8blahrec9blahrec1blahrec2blah");
+
+splice(@a, 1, 3, 'record9', 'rec10'); # delete more than insert
+check_contents("rec0blahrecord9blahrec10blahrec1blahrec2blah");
+splice(@a, 1, 2); # delete more than one
+check_contents("$data");
+
+# (43-62) splicing at the end
+splice(@a, 3, 0, "rec4");
+check_contents("$ {data}rec4blah");
+splice(@a, 3, 1, "rec5"); # same length
+check_contents("$ {data}rec5blah");
+splice(@a, 3, 1, "record5"); # longer
+check_contents("$ {data}record5blah");
+
+splice(@a, 3, 1, "r5"); # shorter
+check_contents("$ {data}r5blah");
+splice(@a, 3, 1); # removal
+check_contents("$data");
+splice(@a, 3, 0); # no-op
+check_contents("$data");
+splice(@a, 3, 0, 'r7', 'rec8'); # insert more than one
+check_contents("$ {data}r7blahrec8blah");
+splice(@a, 3, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
+check_contents("$ {data}rec7blahrecord8blahrec9blah");
+
+splice(@a, 3, 3, 'record9', 'rec10'); # delete more than insert
+check_contents("$ {data}record9blahrec10blah");
+splice(@a, 3, 2); # delete more than one
+check_contents("$data");
+
+# (63-82) splicing with negative subscript
+splice(@a, -1, 0, "rec4");
+check_contents("rec0blahrec1blahrec4blahrec2blah");
+splice(@a, -1, 1, "rec5"); # same length
+check_contents("rec0blahrec1blahrec4blahrec5blah");
+splice(@a, -1, 1, "record5"); # longer
+check_contents("rec0blahrec1blahrec4blahrecord5blah");
+
+splice(@a, -1, 1, "r5"); # shorter
+check_contents("rec0blahrec1blahrec4blahr5blah");
+splice(@a, -1, 1); # removal
+check_contents("rec0blahrec1blahrec4blah");
+splice(@a, -1, 0); # no-op
+check_contents("rec0blahrec1blahrec4blah");
+splice(@a, -1, 0, 'r7', 'rec8'); # insert more than one
+check_contents("rec0blahrec1blahr7blahrec8blahrec4blah");
+splice(@a, -1, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
+check_contents("rec0blahrec1blahr7blahrec8blahrec7blahrecord8blahrec9blah");
+
+splice(@a, -3, 3, 'record9', 'rec10'); # delete more than insert
+check_contents("rec0blahrec1blahr7blahrec8blahrecord9blahrec10blah");
+splice(@a, -4, 3); # delete more than one
+check_contents("rec0blahrec1blahrec10blah");
+
+# (83-84) scrub it all out
+splice(@a, 0, 3);
+check_contents("");
+
+# (85-86) put some back in
+splice(@a, 0, 0, "rec0", "rec1");
+check_contents("rec0blahrec1blah");
+
+# (87-88) what if we remove too many records?
+splice(@a, 0, 17);
+check_contents("");
+
+sub init_file {
+ my $data = shift;
+ open F, "> $file" or die $!;
+ print F $data;
+ close F;
+}
+
+sub check_contents {
+ my $x = shift;
+ local *FH;
+ my $integrity = $o->_check_integrity($file, $ENV{INTEGRITY});
+ print $integrity ? "ok $N\n" : "not ok $N\n";
+ $N++;
+ my $open = open FH, "< $file";
+ my $a;
+ { local $/; $a = <FH> }
+ print (($open && $a eq $x) ? "ok $N\n" : "not ok $N\n");
+ $N++;
+}
+
+END {
+ 1 while unlink $file;
+}
+
diff --git a/lib/Tie/File/11_rv_splice_rs.t b/lib/Tie/File/11_rv_splice_rs.t
new file mode 100644
index 0000000000..f78c25c8d8
--- /dev/null
+++ b/lib/Tie/File/11_rv_splice_rs.t
@@ -0,0 +1,157 @@
+#!/usr/bin/perl
+#
+# Check SPLICE function's return value
+# (04_splice.t checks its effect on the file)
+#
+
+my $file = "tf$$.txt";
+my $data = "rec0blahrec1blahrec2blah";
+
+print "1..45\n";
+
+my $N = 1;
+use Tie::File;
+print "ok $N\n"; $N++; # partial credit just for showing up
+
+my $o = tie @a, 'Tie::File', $file, recsep => 'blah';
+print $o ? "ok $N\n" : "not ok $N\n";
+$N++;
+
+my $n;
+
+# (3-12) splicing at the beginning
+init_file($data);
+
+@r = splice(@a, 0, 0, "rec4");
+check_result();
+@r = splice(@a, 0, 1, "rec5"); # same length
+check_result("rec4");
+@r = splice(@a, 0, 1, "record5"); # longer
+check_result("rec5");
+
+@r = splice(@a, 0, 1, "r5"); # shorter
+check_result("record5");
+@r = splice(@a, 0, 1); # removal
+check_result("r5");
+@r = splice(@a, 0, 0); # no-op
+check_result();
+@r = splice(@a, 0, 0, 'r7', 'rec8'); # insert more than one
+check_result();
+@r = splice(@a, 0, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
+check_result('r7', 'rec8');
+
+@r = splice(@a, 0, 3, 'record9', 'rec10'); # delete more than insert
+check_result('rec7', 'record8', 'rec9');
+@r = splice(@a, 0, 2); # delete more than one
+check_result('record9', 'rec10');
+
+
+# (13-22) splicing in the middle
+@r = splice(@a, 1, 0, "rec4");
+check_result();
+@r = splice(@a, 1, 1, "rec5"); # same length
+check_result('rec4');
+@r = splice(@a, 1, 1, "record5"); # longer
+check_result('rec5');
+
+@r = splice(@a, 1, 1, "r5"); # shorter
+check_result("record5");
+@r = splice(@a, 1, 1); # removal
+check_result("r5");
+@r = splice(@a, 1, 0); # no-op
+check_result();
+@r = splice(@a, 1, 0, 'r7', 'rec8'); # insert more than one
+check_result();
+@r = splice(@a, 1, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
+check_result('r7', 'rec8');
+
+@r = splice(@a, 1, 3, 'record9', 'rec10'); # delete more than insert
+check_result('rec7', 'record8', 'rec9');
+@r = splice(@a, 1, 2); # delete more than one
+check_result('record9','rec10');
+
+# (23-32) splicing at the end
+@r = splice(@a, 3, 0, "rec4");
+check_result();
+@r = splice(@a, 3, 1, "rec5"); # same length
+check_result('rec4');
+@r = splice(@a, 3, 1, "record5"); # longer
+check_result('rec5');
+
+@r = splice(@a, 3, 1, "r5"); # shorter
+check_result('record5');
+@r = splice(@a, 3, 1); # removal
+check_result('r5');
+@r = splice(@a, 3, 0); # no-op
+check_result();
+@r = splice(@a, 3, 0, 'r7', 'rec8'); # insert more than one
+check_result();
+@r = splice(@a, 3, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
+check_result('r7', 'rec8');
+
+@r = splice(@a, 3, 3, 'record9', 'rec10'); # delete more than insert
+check_result('rec7', 'record8', 'rec9');
+@r = splice(@a, 3, 2); # delete more than one
+check_result('record9', 'rec10');
+
+# (33-42) splicing with negative subscript
+@r = splice(@a, -1, 0, "rec4");
+check_result();
+@r = splice(@a, -1, 1, "rec5"); # same length
+check_result('rec2');
+@r = splice(@a, -1, 1, "record5"); # longer
+check_result("rec5");
+
+@r = splice(@a, -1, 1, "r5"); # shorter
+check_result("record5");
+@r = splice(@a, -1, 1); # removal
+check_result("r5");
+@r = splice(@a, -1, 0); # no-op
+check_result();
+@r = splice(@a, -1, 0, 'r7', 'rec8'); # insert more than one
+check_result();
+@r = splice(@a, -1, 2, 'rec7', 'record8', 'rec9'); # insert more than delete
+check_result('rec4');
+
+@r = splice(@a, -3, 3, 'record9', 'rec10'); # delete more than insert
+check_result('rec7', 'record8', 'rec9');
+@r = splice(@a, -4, 3); # delete more than one
+check_result('r7', 'rec8', 'record9');
+
+# (43) scrub it all out
+@r = splice(@a, 0, 3);
+check_result('rec0', 'rec1', 'rec10');
+
+# (44) put some back in
+@r = splice(@a, 0, 0, "rec0", "rec1");
+check_result();
+
+# (45) what if we remove too many records?
+@r = splice(@a, 0, 17);
+check_result('rec0', 'rec1');
+
+sub init_file {
+ my $data = shift;
+ open F, "> $file" or die $!;
+ print F $data;
+ close F;
+}
+
+# actual results are in @r.
+# expected results are in @_
+sub check_result {
+ my @x = @_;
+ s/blah$// for @r;
+ my $good = 1;
+ $good = 0 unless @r == @x;
+ for my $i (0 .. $#r) {
+ $good = 0 unless $r[$i] eq $x[$i];
+ }
+ print $good ? "ok $N\n" : "not ok $N \# was (@r); should be (@x)\n";
+ $N++;
+}
+
+END {
+ 1 while unlink $file;
+}
+
diff --git a/lib/Tie/File/12_longfetch_rs.t b/lib/Tie/File/12_longfetch_rs.t
new file mode 100644
index 0000000000..60f1fd1a50
--- /dev/null
+++ b/lib/Tie/File/12_longfetch_rs.t
@@ -0,0 +1,38 @@
+#!/usr/bin/perl
+#
+# Make sure we can fetch a record in the middle of the file
+# before we've ever looked at any records before it
+#
+# (tests _fill_offsets_to() )
+#
+
+my $file = "tf$$.txt";
+my $data = "rec0blahrec1blahrec2blah";
+
+print "1..5\n";
+
+my $N = 1;
+use Tie::File;
+print "ok $N\n"; $N++;
+
+open F, "> $file" or die $!;
+print F $data;
+close F;
+
+
+my $o = tie @a, 'Tie::File', $file, recsep => 'blah';
+print $o ? "ok $N\n" : "not ok $N\n";
+$N++;
+
+my $n;
+
+# 3-5
+for (2, 1, 0) {
+ print $a[$_] eq "rec${_}blah" ? "ok $N\n" : "not ok $N # rec=$a[$_] ?\n";
+ $N++;
+}
+
+END {
+ 1 while unlink $file;
+}
+
diff --git a/lib/Tie/File/13_size_rs.t b/lib/Tie/File/13_size_rs.t
new file mode 100644
index 0000000000..254f3ab0b0
--- /dev/null
+++ b/lib/Tie/File/13_size_rs.t
@@ -0,0 +1,78 @@
+#!/usr/bin/perl
+#
+# Check FETCHSIZE and SETSIZE functions
+# PUSH POP SHIFT UNSHIFT
+#
+
+my $file = "tf$$.txt";
+my $data = "rec0blahrec1blahrec2blah";
+my ($o, $n);
+
+print "1..10\n";
+
+my $N = 1;
+use Tie::File;
+print "ok $N\n"; $N++;
+
+# 2-3 FETCHSIZE 0-length file
+open F, "> $file" or die $!;
+close F;
+$o = tie @a, 'Tie::File', $file, recsep => 'blah';
+print $o ? "ok $N\n" : "not ok $N\n";
+$N++;
+$n = @a;
+print $n == 0 ? "ok $N\n" : "not ok $N # $n, s/b 0\n";
+$N++;
+
+# Reset everything
+undef $o;
+untie @a;
+
+# 4-5 FETCHSIZE positive-length file
+open F, "> $file" or die $!;
+print F $data;
+close F;
+$o = tie @a, 'Tie::File', $file, recsep => 'blah';
+print $o ? "ok $N\n" : "not ok $N\n";
+$N++;
+$n = @a;
+print $n == 3 ? "ok $N\n" : "not ok $N # $n, s/b 0\n";
+$N++;
+
+# STORESIZE
+# 6 Make it longer:
+$#a = 4;
+check_contents("${data}blahblah");
+
+# 7 Make it longer again:
+$#a = 6;
+check_contents("${data}blahblahblahblah");
+
+# 8 Make it shorter:
+$#a = 4;
+check_contents("${data}blahblah");
+
+# 9 Make it shorter again:
+$#a = 2;
+check_contents($data);
+
+# 10 Get rid of it completely:
+$#a = -1;
+check_contents('');
+
+
+sub check_contents {
+ my $x = shift;
+ local *FH;
+ my $open = open FH, "< $file";
+ my $a;
+ { local $/; $a = <FH> }
+ print (($open && $a eq $x) ? "ok $N\n" : "not ok $N\n");
+ $N++;
+}
+
+
+END {
+ 1 while unlink $file;
+}
+