home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC-Online 1996 May
/
PCOnline_05_1996.bin
/
linux
/
source
/
kernel-s
/
ifs-5.1
/
ifsprogs
/
test.pl
< prev
next >
Wrap
Perl Script
|
1995-10-10
|
24KB
|
1,009 lines
#!/usr/bin/perl
# This test verifies correct function of the Inheriting File System (IFS) for
# a collection of strictly serial operations. This test does NEITHER guarantee
# total correctness of the file system code NOR does it give any indication,
# whether there are incorrectly handled race conditions or not.
require("sys/syscall.ph");
require("linux/errno.ph");
require("linux/stat.ph");
if (!$ARGV[0] || !chdir($ARGV[0])) {
print "usage: test.pl base_directory\n";
exit(1);
}
$A = "a";
$B = "b";
$AB = "a+b";
$first = 1;
sub pass
{
local ($status) = @_;
$status || die "PASS failed ($!)";
}
sub fail
{
local ($status,$expect) = @_;
$status && die "FAIL passed ($!)";
die "FAILed with ".($!+0)." instead of $expect." if $! != $expect;
}
sub create
{
local ($name,$data) = @_;
open(FILE,">$name") || return 0;
if ($data) {
print FILE $data;
}
close FILE;
return 1;
}
sub touch
{
return &create(@_[0],"");
}
sub append
{
local ($name,$data) = @_;
open(FILE,">>$name") || return 0;
if ($data) {
print FILE $data;
}
close FILE;
return 1;
}
sub unlink
{
local ($name) = @_;
return !syscall(&SYS_unlink,$name);
}
sub truncate
{
local ($name,$length) = @_;
open(FILE,">>$name") || die "$!";
truncate(FILE,$length);
close(FILE);
return 1;
}
sub rename
{
local ($old,$new) = @_;
return !syscall(&SYS_rename,$old,$new);
}
sub unwhiteout
{
local ($dir,$name) = @_;
local ($status);
open(DIR,$dir) || die "open directory $dir: $!";
$status = ioctl(DIR,0x53464900,$name);
close(DIR);
return $status;
}
sub tree
{
local ($dir) = @_;
local (@dir,@new,$name,$dot,$dotdot);
opendir(DIR,$dir) || die("opendir $dir: $!");
@dir = readdir(DIR);
closedir(DIR);
@new = ();
$dor = $dotdot = 0;
for (@dir) {
$name = $_;
if ($name eq ".") {
if ($dot) { die "duplicate . in $dir"; }
$dot = 1;
}
elsif ($name eq "..") {
if ($dotdot) { die "duplicate .. in $dir"; }
$dotdot = 1;
}
else {
push(@new,$name);
if (&S_ISDIR((lstat($dir."/".$name))[2])) {
push(@new,grep($_ = $name."/".$_,&tree($dir."/".$name)));
}
}
}
if (!$dot) { die "no . in $dir"; }
if (!$dotdot) { die "no .. in $dir"; }
return @new;
}
sub clean
{
&pass(system("smount -u $AB") == 0);
# &pass(chdir("/"));
# &pass(system("umount /scratch") == 0);
# &pass(system("mount /scratch") == 0);
# &pass(chdir("/scratch"));
$mounted = 0;
for (reverse @left) {
if (m,^(.*)/$,) {
&pass(rmdir($1));
}
elsif (m/^([^-=(|]+)([-=(|].*)?$/) {
&pass(unlink($1));
}
else {
die("Unknown file \"$_\"");
}
}
@left = ();
&pass(rmdir($A));
&pass(rmdir($B));
&pass(rmdir($AB));
}
sub begin
{
$tests++;
print "@_\n";
if (!$first) {
&clean();
}
$first = 0;
&pass(mkdir($A,0777));
&pass(mkdir($B,0777));
&pass(mkdir($AB,0777));
}
sub init
{
local ($dir);
$dir = shift(@_);
for (@_) {
if (m,^(.*)/$,) {
&pass(mkdir($dir."/".$1,0777));
}
elsif (m/^([^-=(]+)(=|->|\(|\|)(.*)$/) {
if ($2 eq "=") { &pass(&create($dir."/".$1,$3)); }
elsif ($2 eq "->") { &pass(symlink($3,$dir."/".$1)); }
elsif ($2 eq "|") { die "not yet supported"; }
elsif ($2 eq "(") { die "not yet supported"; }
else { die "unknown attribute \"$2\""; }
}
else {
&pass(&touch($dir."/".$_));
}
}
}
# Must be called before performing any operations on the IFS in a test
# sequence. test implicitly calls commit.
sub commit
{
if (!$mounted) {
&pass(system("smount -t ifs $A,$B $AB") == 0);
$mounted = 1;
}
}
sub test
{
local ($dir,$mode,$rdev,@dir,@expect,$file);
$dir = shift(@_);
&commit();
if ($dir ne $AB) {
for (@_) {
push(@left,$dir."/".$_);
}
}
@dir = &tree($dir);
for (@dir) {
($mode,$rdev) = (lstat($dir."/".$_))[2,6];
if (&S_ISREG($mode)) { ; }
elsif (&S_ISDIR($mode)) { $_ .= "/"; }
elsif (&S_ISLNK($mode)) { $_ .= "->".readlink($dir."/".$_); }
elsif (&S_ISFIFO($mode)) { $_ .= "|"; }
elsif (&S_ISCHR($mode) || &S_ISBLK($mode)) {
$_ .= sprintf("(%d,%d)",$rdev >> 8,$rdev & 0xff);
}
else {
die "unknown mode ".sprintf("0%o",$mode);
}
}
@expect = sort(@_);
@dir = sort(@dir);
if ($#_ != $#dir) {
die "directories \"@expect\" and \"@dir\" differ in size";
}
for (0..$#_) {
if ($expect[$_] =~ /^([^=]*)=(.*)$/) {
if ($1 ne $dir[$_]) {
die "directories \"@expect\" and \"@dir\" differ";
}
open(FILE,$dir."/".$1) || die "can't open $1: $!";
$file = join("\n",<FILE>);
if ($2 ne $file) {
die "content of file $dir/$1 is \"$file\" instead of \"$2\"";
}
close FILE;
}
else {
if ($expect[$_] ne $dir[$_]) {
die "directories \"@expect\" and \"@dir\" differ";
}
}
}
}
# INITIALIZATION
# system("smount -u /scratch; smount -u $AB; rm -rf $A $B $AB");
# READDIR
&begin("readdir, no files");
&test($A);
&test($B);
&test($AB);
&begin("readdir, on upper layer");
&init($A,"file_a");
&test($A,"file_a");
&test($B);
&test($AB,"file_a");
&begin("readdir, on lower layer");
&init($B,"file_b");
&test($A);
&test($B,"file_b");
&test($AB,"file_b");
&begin("readdir, on both layers");
&init($A,"file_a","file_c");
&init($B,"file_b","file_c");
&test($A,"file_a","file_c");
&test($B,"file_b","file_c");
&test($AB,"file_a","file_b","file_c");
&begin("readdir, on lower layer, whiteout");
&init($A,".../",".../file_b");
&init($B,"file_b");
&test($A,".../",".../file_b");
&test($B,"file_b");
&test($AB);
&begin("readdir, no files, whiteout (corrupt)");
&init($A,".../",".../file");
&init($B);
&test($A,".../",".../file");
&test($B);
&test($AB);
&begin("readdir, multiple directories");
&init($A,"0/","2/","2/3");
&init($B,"1/","2/","2/4");
&test($A,"0/","2/","2/3");
&test($B,"1/","2/","2/4");
&test($AB,"0/","1/","2/","2/3","2/4");
&begin("readdir, lower hidden");
&init($A,"dir/","dir/1=one","dir/2=two",".../",".../dir/");
&init($B,"dir/","dir/3=three");
&test($A,"dir/","dir/1=one","dir/2=two",".../",".../dir/");
&test($B,"dir/","dir/3=three");
&test($AB,"dir/","dir/1=one","dir/2=two");
# READ FILE
&begin("read file, doesn't exist");
&commit();
&fail(open(DUMMY,"$AB/file"),&ENOENT);
&begin("read file, doesn't exist, whiteout (corrupt)");
&init($A,".../",".../file");
&test($A,".../",".../file");
&fail(open(DUMMY,"$AB/file"),&ENOENT);
&begin("read file, on upper layer");
&init($A,"file=just_a_file");
&test($A,"file=just_a_file");
&test($AB,"file=just_a_file");
&begin("read file, on lower layer");
&init($B,"file=just_a_file");
&test($B,"file=just_a_file");
&test($AB,"file=just_a_file");
&begin("read file, on both layers");
&init($A,"file=file_on_A");
&init($B,"file=file_on_B");
&test($A,"file=file_on_A");
&test($B,"file=file_on_B");
&test($AB,"file=file_on_A");
&begin("read file, on upper layer, whiteout (corrupt)");
&init($A,"file=just_a_file",".../",".../file");
&test($A,"file=just_a_file",".../",".../file");
&fail(open(DUMMY,"$AB/file"),&ENOENT);
&begin("read file, on lower layer, whiteout");
&init($A,".../",".../file");
&init($B,"file=a_file");
&test($A,".../",".../file");
&test($B,"file=a_file");
&fail(open(DUMMY,"$AB/file"),&ENOENT);
&begin("read file, on both layers, whiteout (corrupt)");
&init($A,"file=file_on_A",".../",".../file");
&init($B,"file=file_on_B");
&test($A,"file=file_on_A",".../",".../file");
&test($B,"file=file_on_B");
&fail(open(DUMMY,"$AB/file"),&ENOENT);
&begin("read file ..., on upper layer (invalid name)");
&init($A,"...");
&commit();
&fail(open(DUMMY,"$AB/..."),&ENOENT);
&test($A,"...");
# CREATE FILE
&begin("create file, file is new");
&commit();
&pass(&create("$A/file","a_file_..."));
&test($A,"file=a_file_...");
&test($AB,"file=a_file_...");
&begin("create file, file is new, whiteout (corrupt)");
&init($A,".../",".../file");
&commit();
&pass(&create("$AB/file","a_file_..."));
&test($A,"file=a_file_...",".../");
&test($AB,"file=a_file_...");
&begin("create file, exists on upper layer");
&init($A,"file=on A");
&commit();
&pass(&create("$AB/file","a_file"));
&test($A,"file=a_file");
&test($AB,"file=a_file");
&begin("create file, exists on lower layer");
&init($B,"file=on_B");
&commit();
&pass(&create("$AB/file","a_file_..."));
&test($A,"file=a_file_...");
&test($B,"file=on_B");
&test($AB,"file=a_file_...");
&begin("create file, exists on upper layer, whiteout (corrupt)");
&init($A,"file=on_A",".../",".../file");
&commit();
&fail(&create("$AB/file","a_file"),&EEXIST);
&test($A,"file=on_A",".../",".../file");
&test($AB);
&begin("create file, exists on lower layer, whiteout");
&init($A,".../",".../file");
&init($B,"file=on_B");
&commit();
&pass(&create("$AB/file","a_file_..."));
&test($A,"file=a_file_...",".../");
&test($B,"file=on_B");
&test($AB,"file=a_file_...");
&begin("create file ..., new file (invalid name)");
&commit();
&fail(&create("$AB/...",""),&EINVAL);
&test($A);
&begin("create file, with entire directory tree");
&init($A,"1/","1/2/","1/2/3/");
&init($B,"1/","1/2/","1/2/3/");
&commit();
&pass(&create("$AB/1/2/3/file",""));
&test($A,"1/","1/2/","1/2/3/","1/2/3/file");
&test($B,"1/","1/2/","1/2/3/");
&test($AB,"1/","1/2/","1/2/3/","1/2/3/file");
&begin("create file, with partial directory tree");
&init($A,"1/");
&init($B,"1/","1/2/","1/2/3/");
&commit();
&pass(&create("$AB/1/2/3/file",""));
&test($A,"1/","1/2/","1/2/3/","1/2/3/file");
&test($B,"1/","1/2/","1/2/3/");
&test($AB,"1/","1/2/","1/2/3/","1/2/3/file");
&begin("create file, with empty directory tree");
&init($A);
&init($B,"1/","1/2/","1/2/3/");
&commit();
&pass(&create("$AB/1/2/3/file",""));
&test($A,"1/","1/2/","1/2/3/","1/2/3/file");
&test($B,"1/","1/2/","1/2/3/");
&test($AB,"1/","1/2/","1/2/3/","1/2/3/file");
# APPEND TO FILE
&begin("append to existing file, upper layer");
&init($A,"file=on_A");
&commit();
&pass(&append("$AB/file","_more"));
&test($A,"file=on_A_more");
&test($B);
&test($AB,"file=on_A_more");
&begin("append to existing file, lower layer");
&init($B,"file=on_B");
&commit();
&pass(&append("$AB/file","_more"));
&test($A,"file=on_B_more");
&test($B,"file=on_B");
&test($AB,"file=on_B_more");
&begin("append to existing file, both layers");
&init($A,"file=on_A");
&init($B,"file=on_B");
&commit();
&pass(&append("$AB/file","_more"));
&test($A,"file=on_A_more");
&test($B,"file=on_B");
&test($AB,"file=on_A_more");
&begin("append to file, with entire directory tree");
&init($A,"1/","1/2/","1/2/3/");
&init($B,"1/","1/2/","1/2/3/","1/2/3/file=B");
&commit();
&pass(&append("$AB/1/2/3/file","_more"));
&test($A,"1/","1/2/","1/2/3/","1/2/3/file=B_more");
&test($B,"1/","1/2/","1/2/3/","1/2/3/file=B");
&test($AB,"1/","1/2/","1/2/3/","1/2/3/file=B_more");
&begin("append to file, with partial directory tree");
&init($A,"1/");
&init($B,"1/","1/2/","1/2/3/","1/2/3/file=B");
&commit();
&pass(&append("$AB/1/2/3/file","_more"));
&test($A,"1/","1/2/","1/2/3/","1/2/3/file=B_more");
&test($B,"1/","1/2/","1/2/3/","1/2/3/file=B");
&test($AB,"1/","1/2/","1/2/3/","1/2/3/file=B_more");
&begin("append to file, with empty directory tree");
&init($A);
&init($B,"1/","1/2/","1/2/3/","1/2/3/file=B");
&commit();
&pass(&append("$AB/1/2/3/file","_more"));
&test($A,"1/","1/2/","1/2/3/","1/2/3/file=B_more");
&test($B,"1/","1/2/","1/2/3/","1/2/3/file=B");
&test($AB,"1/","1/2/","1/2/3/","1/2/3/file=B_more");
# TRUNCATE FILE
&begin("truncating file, upper layer");
&init($A,"file=abcde");
&commit();
&pass(&truncate("$AB/file",2));
&test($A,"file=ab");
&test($B);
&test($AB,"file=ab");
&begin("truncating file, lower layer");
&init($B,"file=abcde");
&commit();
&pass(&truncate("$AB/file",3));
&test($A,"file=abc");
&test($B,"file=abcde");
&test($AB,"file=abc");
# UNLINK
&begin("unlink, file doesn't exist");
&commit();
&fail(&unlink("$AB/file"),&ENOENT);
&begin("unlink, file doesn't exist, whiteout (corrupt)");
&init($A,".../",".../file");
&commit();
&fail(&unlink("$AB/file"),&ENOENT);
&test($A,".../",".../file");
&test($AB);
&begin("unlink, exists on upper layer");
&init($A,"file");
&commit();
&pass(&unlink("$AB/file"));
&test($A);
&test($AB);
&begin("unlink, exists on lower layer");
&init($B,"file");
&commit();
&pass(&unlink("$AB/file"));
&test($A,".../",".../file");
&test($B,"file");
&test($AB);
&begin("unlink, exists on both layers");
&init($A,"file=A");
&init($B,"file=B");
&commit();
&pass(&unlink("$AB/file"));
&test($A,".../",".../file");
&test($B,"file=B");
&test($AB);
&begin("unlink, exists on upper layer, whiteout (corrupt)");
&init($A,"file",".../",".../file");
&commit();
&fail(&unlink("$AB/file"),&ENOENT);
&test($A,"file",".../",".../file");
&test($AB);
&begin("unlink, exists on lower layer, whiteout");
&init($A,".../",".../file");
&init($B,"file");
&commit();
&fail(&unlink("$AB/file"),&ENOENT);
&test($A,".../",".../file");
&test($B,"file");
&test($AB);
&begin("unlink, with entire directory tree");
&init($A,"1/","1/2/","1/2/3/");
&init($B,"1/","1/2/","1/2/3/","1/2/3/file");
&commit();
&pass(&unlink("$AB/1/2/3/file"));
&test($A,"1/","1/2/","1/2/3/","1/2/3/.../","1/2/3/.../file");
&test($B,"1/","1/2/","1/2/3/","1/2/3/file");
&test($AB,"1/","1/2/","1/2/3/");
&begin("unlink, with partial directory tree");
&init($A,"1/");
&init($B,"1/","1/2/","1/2/3/","1/2/3/file");
&commit();
&pass(&unlink("$AB/1/2/3/file"));
&test($A,"1/","1/2/","1/2/3/","1/2/3/.../","1/2/3/.../file");
&test($B,"1/","1/2/","1/2/3/","1/2/3/file");
&test($AB,"1/","1/2/","1/2/3/");
&begin("unlink, with empty directory tree");
&init($A);
&init($B,"1/","1/2/","1/2/3/","1/2/3/file");
&commit();
&pass(&unlink("$AB/1/2/3/file"));
&test($A,"1/","1/2/","1/2/3/","1/2/3/.../","1/2/3/.../file");
&test($B,"1/","1/2/","1/2/3/","1/2/3/file");
&test($AB,"1/","1/2/","1/2/3/");
# MKDIR
&begin("mkdir, directory is new");
&commit();
&pass(mkdir("$AB/dir",0777));
&test($A,"dir/");
&test($B);
&test($AB,"dir/");
&begin("mkdir, directory is new, whiteout (corrupt)");
&init($A,".../",".../dir");
&commit();
&pass(mkdir("$AB/dir",0777));
&test($A,"dir/",".../");
&test($B);
&test($AB,"dir/");
&begin("mkdir, exists on upper layer");
&init($A,"dir/");
&commit();
&fail(mkdir("$AB/dir",0777),&EEXIST);
&test($A,"dir/");
&test($B);
&test($AB,"dir/");
&begin("mkdir, exists on lower layer");
&init($B,"dir/");
&commit();
&fail(mkdir("$AB/dir",0777),&EEXIST);
&test($A);
&test($B,"dir/");
&test($AB,"dir/");
&begin("mkdir, exists on upper layer, whiteout (corrupt)");
&init($A,"dir/",".../",".../dir");
&commit();
&fail(mkdir("$AB/dir",0777),&EEXIST);
&test($A,"dir/",".../",".../dir");
&test($B);
&test($AB);
&begin("mkdir, exists on lower layer, whiteout");
&init($A,".../",".../dir");
&init($B,"dir/");
&commit();
&pass(mkdir("$AB/dir",0777));
&test($A,"dir/",".../",".../dir/");
&test($B,"dir/");
&test($AB,"dir/");
# RMDIR
&begin("rmdir, directory doesn't exist");
&commit();
&fail(rmdir("$A/dir"),&ENOENT);
&test($AB);
&begin("rmdir, directory doesn't exist, whiteout (corrupt)");
&init($A,".../",".../dir");
&commit();
&fail(rmdir("$AB/dir"),&ENOENT);
&test($A,".../",".../dir");
&test($AB);
&begin("rmdir, exists on upper layer, empty");
&init($A,"dir/");
&commit();
&pass(rmdir("$AB/dir"));
&test($A);
&test($AB);
&begin("rmdir, exists on lower layer, empty");
&init($B,"dir/");
&commit();
&pass(rmdir("$AB/dir"));
&test($A,".../",".../dir");
&test($B,"dir/");
&test($AB);
&begin("rmdir, exists on upper layer, empty, whiteout (corrupt)");
&init($A,"dir/",".../",".../dir");
&commit();
&fail(rmdir("$AB/dir"),&ENOENT);
&test($A,"dir/",".../",".../dir");
&test($AB);
&begin("rmdir, exists on lower layer, empty, whiteout");
&init($A,".../",".../dir");
&init($B,"dir/");
&commit();
&fail(rmdir("$AB/dir"),&ENOENT);
&test($A,".../",".../dir");
&test($B,"dir/");
&test($AB);
&begin("rmdir, exists on upper layer, full");
&init($A,"dir/","dir/1","dir/2");
&commit();
&fail(rmdir("$AB/dir"),&ENOTEMPTY);
&test($A,"dir/","dir/1","dir/2");
&test($AB,"dir/","dir/1","dir/2");
&begin("rmdir, exists on both layers, files in lower");
&init($A,"dir/");
&init($B,"dir/","dir/1","dir/2");
&commit();
&fail(rmdir("$AB/dir"),&ENOTEMPTY);
&test($A,"dir/");
&test($B,"dir/","dir/1","dir/2");
&test($AB,"dir/","dir/1","dir/2");
&begin("rmdir, exists on lower layer, full");
&init($B,"dir/","dir/1","dir/2");
&commit();
&fail(rmdir("$AB/dir"),&ENOTEMPTY);
&test($A);
&test($B,"dir/","dir/1","dir/2");
&test($AB,"dir/","dir/1","dir/2");
&begin("rmdir, exists on both layers, files in lower, all files whited out");
&init($A,"dir/","dir/.../","dir/.../1","dir/.../2");
&init($B,"dir/","dir/1","dir/2");
&commit();
&pass(rmdir("$AB/dir"));
&test($A,".../",".../dir");
&test($B,"dir/","dir/1","dir/2");
&test($AB);
&begin("rmdir, exists on both layers, empty, lower hidden");
&init($A,"dir/",".../",".../dir/");
&init($B,"dir/");
&commit();
&pass(rmdir("$AB/dir"));
&test($A,".../",".../dir");
&test($B,"dir/");
&test($AB);
# SYMLINK
&begin("symlink, file is new");
&commit();
&pass(symlink("dummy","$AB/link"));
&test($A,"link->dummy");
&test($AB,"link->dummy");
&begin("symlink, file is new, whiteout (corrupt)");
&init($A,".../",".../link");
&commit();
&pass(symlink("dummy","$AB/link"));
&test($A,"link->dummy",".../");
&test($AB,"link->dummy");
&begin("symlink, exists on upper layer");
&init($A,"file");
&commit();
&fail(symlink("dummy","$AB/file"),&EEXIST);
&test($A,"file");
&test($AB,"file");
&begin("symlink, exists on lower layer");
&init($B,"file");
&commit();
&fail(symlink("dummy","$AB/file"),&EEXIST);
&test($A);
&test($B,"file");
&test($AB,"file");
&begin("symlink, exists on upper layer, whiteout (corrupt)");
&init($A,"link",".../",".../link");
&commit();
&fail(symlink("dummy","$AB/link"),&EEXIST);
&test($A,"link",".../",".../link");
&test($AB);
&begin("symlink, exists on lower layer, whiteout");
&init($A,".../",".../link");
&init($B,"link");
&commit();
&pass(symlink("dummy","$AB/link"));
&test($A,"link->dummy",".../");
&test($B,"link");
&test($AB,"link->dummy");
# LINK
# &begin("link, same FS, file is new");
# &begin("link, same FS, file is new, whiteout");
# &begin("link, same FS, exists on upper layer");
# &begin("link, same FS, exists on lower layer");
# &begin("link, same FS, exists on upper layer, whiteout");
# &begin("link, same FS, exists on lower layer, whiteout");
# &begin("link, different FS");
# MKNOD
# &begin("mknod, file is new");
# &begin("mknod, file is new, whiteout");
# &begin("mknod, exists on upper layer");
# &begin("mknod, exists on lower layer");
# &begin("mknod, exists on upper layer, whiteout");
# &begin("mknod, exists on lower layer, whiteout");
# RENAME
&begin("rename file, non-existing source name");
&init($A);
&commit();
&fail(&rename("$AB/src","$AB/dst"),&ENOENT);
&test($A);
&test($AB);
&begin("rename file, non-existing source name, whiteout (corrupt)");
&init($A,".../",".../src");
&commit();
&fail(&rename("$AB/src","$AB/dst"),&ENOENT);
&test($A,".../",".../src");
&test($AB);
&begin("rename file, src and dst on the same FS, same directory");
&init($A,"src=test");
&commit();
&pass(&rename("$AB/src","$AB/dst"));
&test($A,"dst=test");
&test($AB,"dst=test");
&begin("rename file, same FS, same directory, whiteout");
&init($A,"src",".../",".../src");
&commit();
&fail(&rename("$AB/src","$AB/dst"),&ENOENT);
&test($A,"src",".../",".../src");
&test($AB);
&begin("rename file, same FS, same directory, dst whiteout");
&init($A,"src=test",".../",".../dst");
&init($B,"dst");
&commit();
&pass(&rename("$AB/src","$AB/dst"));
&test($A,"dst=test",".../");
&test($B,"dst");
&test($AB,"dst=test");
&begin("rename file, same FS, different directory");
&init($A,"src=test","dir/");
&commit();
&pass(&rename("$AB/src","$AB/dir/dst"));
&test($A,"dir/","dir/dst=test");
&test($AB,"dir/","dir/dst=test");
&begin("rename file, same FS, different directory, src whiteout");
&init($A,"src",".../",".../src","dir/");
&commit();
&fail(&rename("$AB/src","$AB/dir/dst"),&ENOENT);
&test($A,"src",".../",".../src","dir/");
&test($AB,"dir/");
&begin("rename file, same FS, different directory, dst whiteout");
&init($A,"src=foo","dir/","dir/.../","dir/.../dst");
&init($B,"dir/","dir/dst=bar");
&commit();
&pass(&rename("$AB/src","$AB/dir/dst"));
&test($A,"dir/","dir/.../","dir/dst=foo");
&test($B,"dir/","dir/dst=bar");
&test($AB,"dir/","dir/dst=foo");
&begin("rename file, same FS, diff. directory, dst ex. & whiteout (corrupt)");
&init($A,"src=foo","dir/","dir/.../","dir/.../dst","dir/dst=baz");
&init($B,"dir/","dir/dst=bar");
&commit();
&pass(&rename("$AB/src","$AB/dir/dst"));
&test($A,"dir/","dir/.../","dir/dst=foo");
&test($B,"dir/","dir/dst=bar");
&test($AB,"dir/","dir/dst=foo");
&begin("rename file, same FS, different directory, dst dir. whiteout");
&init($A,"src=foo","dir/",".../",".../dir");
&init($B,"dir/");
&commit();
&fail(&rename("$AB/src","$AB/dir/dst"),&ENOENT);
&test($A,"src=foo","dir/",".../",".../dir");
&test($B,"dir/");
&test($AB,"src=foo");
&begin("rename file, same FS, different directory, incomplete path");
&init($A,"src=foo");
&init($B,"dir/");
&commit();
&pass(&rename("$AB/src","$AB/dir/dst"));
&test($A,"dir/","dir/dst=foo");
&test($B,"dir/");
&test($AB,"dir/","dir/dst=foo");
&begin("rename file, same FS, diff. level, same directory");
&init($A);
&init($B,"src=test");
&commit();
&pass(&rename("$AB/src","$AB/dst"));
&test($A,"dst=test",".../",".../src");
&test($B,"src=test");
&test($AB,"dst=test");
&begin("rename file, same FS, diff. level, different directory");
&init($A);
&init($B,"dir/","dir/src=foo");
&commit();
&pass(&rename("$AB/dir/src","$AB/dst"));
&test($A,"dst=foo","dir/","dir/.../","dir/.../src",".../");
&test($B,"dir/","dir/src=foo");
&test($AB,"dst=foo","dir/");
&begin("rename file, same FS, diff. level, diff. dir., dst exists on upper");
&init($A,"dst=foo");
&init($B,"dir/","dir/src=bar");
&commit();
&pass(&rename("$AB/dir/src","$AB/dst"));
&test($A,"dst=bar","dir/","dir/.../","dir/.../src",".../");
&test($B,"dir/","dir/src=bar");
&test($AB,"dst=bar","dir/");
&begin("rename file, same FS, diff. level, diff. dir., dst exists on lower");
&init($A);
&init($B,"dst=foo","dir/","dir/src=bar");
&commit();
&pass(&rename("$AB/dir/src","$AB/dst"));
&test($A,"dst=bar","dir/","dir/.../","dir/.../src",".../");
&test($B,"dst=foo","dir/","dir/src=bar");
&test($AB,"dst=bar","dir/");
&begin("rename file, same FS, diff. level, different directory, whiteout");
&init($A,".../",".../src");
&init($B,"src=test");
&commit();
&fail(&rename("$AB/src","$AB/dir/dst"),&ENOENT);
&test($A,".../",".../src");
&test($B,"src=test");
&test($AB);
# &begin("rename file, different FS, top-level");
# &begin("rename file, different FS, top-level, whiteout");
# &begin("rename file, different FS, different levels, 'same' dir.");
# &begin("rename file, different FS, different levels, 'diff.' dir.");
# &begin("rename file, different FS, different levels, dd, whiteout");
# UNWHITEOUT
&begin("unwhiteout file, does not exist, no whiteout");
&init($A);
&commit();
&fail(&unwhiteout("$AB","file"),&ENOENT);
&test($A);
&test($AB);
&begin("unwhiteout file, does not exist, whiteout (corrupt)");
&init($A,".../",".../file");
&commit();
&pass(&unwhiteout("$AB","file"));
&test($A,".../");
&test($AB);
&begin("unwhiteout file, exists on upper, no whiteout");
&init($A,"file=foo");
&commit();
&fail(&unwhiteout("$AB","file"),&ENOENT);
&test($A,"file=foo");
&test($AB,"file=foo");
&begin("unwhiteout file, exists on upper, whiteout (corrupt)");
&init($A,"file",".../",".../file");
&commit();
&pass(&unwhiteout("$AB","file"));
&test($A,"file",".../");
&test($AB,"file");
&begin("unwhiteout file, exists on lower, no whiteout");
&init($A);
&init($B,"file=test");
&commit();
&fail(&unwhiteout("$AB","file"),&ENOENT);
&test($A);
&test($B,"file=test");
&test($AB,"file=test");
&begin("unwhiteout file, exists on lower, whiteout");
&init($A,".../",".../file");
&init($B,"file=test");
&commit();
&pass(&unwhiteout("$AB","file"));
&test($A,".../");
&test($B,"file=test");
&test($AB,"file=test");
# Missing test:
# create path across file systems
&clean();
print "Passed all $tests test sequences.\n";
exit(0);