Quiq/t/bin/Quiq/Path.t
#!/usr/bin/env perl
package Quiq::Path::Test;
use base qw/Quiq::Test::Class/;
use v5.10;
use strict;
use warnings;
use utf8;
# -----------------------------------------------------------------------------
sub test_loadClass : Init(1) {
shift->useOk('Quiq::Path');
}
# -----------------------------------------------------------------------------
sub test_append : Test(2) {
my $self = shift;
my $file = "/tmp/test_append$$";
Quiq::Path->append($file,"A\n");
my $data = Quiq::Path->read($file);
$self->is($data,"A\n");
Quiq::Path->append($file,"B\n");
$data = Quiq::Path->read($file);
$self->is($data,"A\nB\n");
Quiq::Path->delete($file);
}
# -----------------------------------------------------------------------------
sub test_checkFileSecurity : Test(4) {
my $self = shift;
my $p = Quiq::Path->new;
my $file = $p->tempFile;
$p->chmod($file,0600);
eval {$p->checkFileSecurity($file)};
$self->ok(!$@);
$p->chmod($file,0640);
eval {$p->checkFileSecurity($file)};
$self->ok($@);
eval {$p->checkFileSecurity($file,1)};
$self->ok(!$@);
$p->chmod($file,0642);
eval {$p->checkFileSecurity($file,1)};
$self->ok($@);
}
# -----------------------------------------------------------------------------
sub test_compareData : Test(2) {
my $self = shift;
my $file = '/tmp/compareData.txt';
Quiq::Path->write($file,'a');
my $bool = Quiq::Path->compareData($file,'a');
$self->is($bool,0);
$bool = Quiq::Path->compareData($file,'b');
$self->is($bool,1);
Quiq::Path->delete($file);
}
# -----------------------------------------------------------------------------
sub test_copy : Test(1) {
my $self = shift;
my $src = "/tmp/copy1.txt";
my $srcData = "$$\n";
my $dest = "/tmp/copy2.txt";
Quiq::Path->write($src,$srcData);
Quiq::Path->copy($src,$dest);
my $destData = Quiq::Path->read($dest);
$self->is($srcData,$destData);
Quiq::Path->delete($src);
Quiq::Path->delete($dest);
}
# -----------------------------------------------------------------------------
sub test_newlineStr : Test(3) {
my $self = shift;
my $testFile = '/tmp/newlineStr.tst';
for my $nlStr ("\cJ","\cM\cJ","\cM") { # LF, CRLF, CR
# Datei schreiben
my $fh = Quiq::FileHandle->new('>',$testFile);
$fh->binmode;
for my $line (qw/Zeile1 Zeile2 Zeile3/) {
$fh->print($line.$nlStr);
}
$fh->close;
# Zeilentrenner bestimmen
my $nlStr2 = Quiq::Path->newlineStr($testFile);
$self->is($nlStr2,$nlStr);
}
Quiq::Path->delete($testFile);
}
# -----------------------------------------------------------------------------
sub test_read : Test(4) {
my $self = shift;
my $file = "/tmp/test_read$$";
Quiq::Path->write($file,"Hallo\n");
my $data = Quiq::Path->read($file);
$self->is($data,"Hallo\n");
Quiq::Path->write($file,"1\n2\n3\n");
$data = Quiq::Path->read($file,-skipLines=>2);
$self->is($data,"3\n");
Quiq::Path->write($file,"1\n#2\n3\n# 4\n5\n");
$data = Quiq::Path->read($file,-skip=>qr/^#/);
$self->is($data,"1\n3\n5\n");
Quiq::Path->write($file,"1\n2\n3\n4\n5\n");
$data = Quiq::Path->read($file,-maxLines=>3);
$self->is($data,"1\n2\n3\n");
# aufräumen
Quiq::Path->delete($file);
}
# -----------------------------------------------------------------------------
sub test_tempFile: Test(4) {
my $self = shift;
my $path;
{
my $file = Quiq::Path->tempFile;
$path = "$file";
my $tempDir = $ENV{'TMPDIR'};
if (!defined($tempDir) || !-d $tempDir) {
$tempDir = '/tmp';
}
$self->ok(-f $file);
$self->like($file,qr|^$tempDir/|);
$self->like(sprintf('%s',$file),qr|^$tempDir/|);
}
$self->ok(!-d $path);
}
# -----------------------------------------------------------------------------
sub test_unindent : Test(3) {
my $self = shift;
my $p = Quiq::Path->new;
my $original = << ' __EOT__';
Dies ist der
erste Absatz.
Dies ist ein
zweiter Absatz.
__EOT__
# Einrückung entfernen
my $expected = Quiq::Unindent->hereDoc($original);
my $file = $p->tempFile($original);
$p->unindent($file);
my $data = $p->read($file);
$self->is($data,$expected,'Einrückung wurde entfernt');
# Ein wiederholter Aufruf ändert nichts an der Datei (auch nicht mtime)
$expected = $p->mtime($file);
sleep 1;
$self->isnt($expected,time,'Zeit ist vergangen');
$p->unindent($file);
my $mtime = $p->mtime($file);
$self->is($mtime,$expected,'Datei wurde nicht geändert');
}
# -----------------------------------------------------------------------------
sub test_write : Test(3) {
my $self = shift;
my $file = "/tmp/test_write$$";
Quiq::Path->write($file);
$self->is(Quiq::Path->isEmpty($file),1);
Quiq::Path->write($file,'x');
$self->is(Quiq::Path->read($file),'x');
Quiq::Path->write($file,'y',-append=>1);
$self->is(Quiq::Path->read($file),'xy');
Quiq::Path->delete($file);
}
# -----------------------------------------------------------------------------
sub test_find : Test(5) {
my $self = shift;
# Test-Verzeichnisstruktur:
#
# /tmp/$$/a
# /tmp/$$/a/b
# /tmp/$$/a/b/c
# /tmp/$$/a/b/c/d
# /tmp/$$/a/b/c/d/y.txt (Datei)
# /tmp/$$/a/b/e
# /tmp/$$/a/b/e/f
# /tmp/$$/a/x.txt (Datei)
my $root = "/tmp/$$";
Quiq::Path->mkdir("$root/a/b/c/d",-recursive=>1);
Quiq::Path->mkdir("$root/a/b/e/f",-recursive=>1);
my $f1 = "$root/a/b/c/d/y.txt";
Quiq::Path->write($f1,'');
my $f2 = "$root/a/x.txt";
Quiq::Path->write($f2,'');
my @paths = sort Quiq::Path->find("$root/a",-type=>'f');
$self->isDeeply(\@paths,[$f1,$f2]);
@paths = sort Quiq::Path->find("$root/a",-type=>'d');
$self->is(scalar(@paths),6);
@paths = sort Quiq::Path->find("$root/a");
$self->is(scalar(@paths),8);
@paths = Quiq::Path->find("$root/x",-sloppy=>1);
$self->is(scalar(@paths),0);
eval {Quiq::Path->find("$root/x")};
$self->like($@,qr/PATH-00011/);
Quiq::Path->delete($root);
}
# -----------------------------------------------------------------------------
sub test_findProgram : Test(1) {
my $self = shift;
my $path = Quiq::Path->findProgram('ls',1);
$self->like($path,qr|/ls$|);
}
# -----------------------------------------------------------------------------
sub test_mkdir : Test(3) {
my $self = shift;
my $path = "/tmp/mkdir$$/a/b";
eval {Quiq::Path->mkdir($path)};
$self->like($@,qr/PATH-00004/);
$path = "/tmp/mkdir$$";
Quiq::Path->mkdir($path);
$self->is(-d $path,1);
Quiq::Path->mkdir($path,-recursive=>1);
$self->ok(-e $path);
Quiq::Path->delete("/tmp/mkdir$$");
}
# -----------------------------------------------------------------------------
sub test_tempDir: Test(4) {
my $self = shift;
my $path;
{
my $dir = Quiq::Path->tempDir;
$path = "$dir";
my $tempDir = $ENV{'TMPDIR'};
if (!defined($tempDir) || !-d $tempDir) {
$tempDir = '/tmp';
}
$self->ok(-d $dir);
$self->like($dir,qr|^$tempDir/|);
$self->like(sprintf('%s',$dir),qr|^$tempDir/|);
}
$self->ok(!-d $path);
}
# -----------------------------------------------------------------------------
sub test_absolute : Test(4) {
my $self = shift;
my $cwd = Quiq::Process->cwd;
my $path = Quiq::Path->absolute;
$self->is($path,$cwd);
$path = Quiq::Path->absolute('.');
$self->is($path,$cwd);
$path = Quiq::Path->absolute('/tmp');
$self->is($path,'/tmp');
$path = Quiq::Path->absolute('tmp');
$self->is($path,"$cwd/tmp");
}
# -----------------------------------------------------------------------------
sub test_basename : Test(3) {
my $self = shift;
my $base = Quiq::Path->basename('datei');
$self->is($base,'datei');
$base = Quiq::Path->basename('datei.ext');
$self->is($base,'datei');
$base = Quiq::Path->basename('/ein/pfad/datei.ext');
$self->is($base,'datei');
}
# -----------------------------------------------------------------------------
sub test_basePath : Test(4) {
my $self = shift;
my $base = Quiq::Path->basePath('datei');
$self->is($base,'datei');
$base = Quiq::Path->basePath('datei.ext');
$self->is($base,'datei');
$base = Quiq::Path->basePath('/ein/pfad/datei.ext');
$self->is($base,'/ein/pfad/datei');
$base = Quiq::Path->basePath('/ein/pfad/datei.ext1.ext2');
$self->is($base,'/ein/pfad/datei.ext1');
}
# -----------------------------------------------------------------------------
sub test_chmod : Test(3) {
my $self = shift;
my $file = "/tmp/chmod$$.txt";
Quiq::Path->write($file);
Quiq::Path->chmod($file,0666);
$self->is(0666,Quiq::Path->mode($file));
Quiq::Path->chmod($file,0644);
$self->is(0644,Quiq::Path->mode($file));
Quiq::Path->delete($file);
eval {Quiq::Path->chmod($file,0444) };
$self->like($@,qr/PATH-00003/);
}
# -----------------------------------------------------------------------------
sub test_delete : Test(5) {
my $self = shift;
eval {Quiq::Path->delete('/does/not/exist')};
$self->ok(!$@);
# Testverzeichnis erzeugen
(my $dir) = (my $path) = "/tmp/test_delete$$";
mkdir $path;
for (qw/a b c/) {
$path .= "/$_";
mkdir $path;
}
my $file = "$path/f.txt";
Quiq::Path->write($file,"bla\n");
# Datei
$self->ok(-e $file);
Quiq::Path->delete($file);
$self->ok(!-e $file);
# Verzeichnis
$self->ok(-e $dir);
Quiq::Path->delete($dir);
$self->ok(!-e $dir);
}
# -----------------------------------------------------------------------------
sub test_dir : Test(2) {
my $self = shift;
my $base = Quiq::Path->dir('datei.ext');
$self->is($base,'');
$base = Quiq::Path->dir('/ein/pfad/datei.ext');
$self->is($base,'/ein/pfad');
}
# -----------------------------------------------------------------------------
sub test_expandTilde : Test(2) {
my $self = shift;
my $path1 = '/test';
my $path2 = Quiq::Path->expandTilde('/test');
$self->is($path1,$path2);
$path1 = '~/test';
$path2 = Quiq::Path->expandTilde('~/test');
$self->isnt($path1,$path2);
}
# -----------------------------------------------------------------------------
sub test_filename : Test(2) {
my $self = shift;
my $file = Quiq::Path->filename('datei');
$self->is($file,'datei');
$file = Quiq::Path->filename('/ein/pfad/datei');
$self->is($file,'datei');
}
# -----------------------------------------------------------------------------
sub test_glob : Test(5) {
my $self = shift;
# Testverzeichnis erzeugen
my $dir = "/tmp/test_glob$$";
Quiq::Path->mkdir($dir);
for (qw/a1 b2 c3/) {
Quiq::Path->write("$dir/$_");
}
# Listkontext
my @paths = Quiq::Path->glob("$dir/*");
$self->isDeeply(\@paths,["$dir/a1","$dir/b2","$dir/c3",]);
# Skalarkontext
my $path = Quiq::Path->glob("$dir/b*");
$self->is($path,"$dir/b2");
eval {Quiq::Path->glob("$dir/*")};
$self->like($@,qr/PATH-00015/);
eval {Quiq::Path->glob("$dir/bb*")};
$self->like($@,qr/PATH-00014/);
eval {Quiq::Path->glob("$dir/*")};
$self->like($@,qr/PATH-00015/);
Quiq::Path->delete($dir);
}
# -----------------------------------------------------------------------------
sub test_isEmpty_file : Test(3) {
my $self = shift;
my $file = "/tmp/test_isEmpty$$";
Quiq::Path->write($file);
my $bool = Quiq::Path->isEmpty($file);
$self->is($bool,1);
Quiq::Path->write($file,'x');
$bool = Quiq::Path->isEmpty($file);
$self->is($bool,0);
# aufräumen
Quiq::Path->delete($file);
$self->ok(!-e $file);
}
sub test_isEmpty_dir : Test(3) {
my $self = shift;
my $dir = "/tmp/test_isEmpty$$";
mkdir $dir;
my $val = Quiq::Path->isEmpty($dir);
$self->is($val,1);
mkdir $dir;
my $file = "$dir/f.txt";
Quiq::Path->write($file,"bla\n");
$val = Quiq::Path->isEmpty($dir);
$self->is($val,0);
# aufräumen
Quiq::Path->delete($dir);
$self->ok(!-d $dir);
}
# -----------------------------------------------------------------------------
sub test_mtime : Test(4) {
my $self = shift;
my $time = time;
my $file = '/tmp/mtime.txt';
Quiq::Path->delete($file);
# Nicht-existenter Pfad
my $mtime = Quiq::Path->mtime($file);
$self->ok($mtime == 0);
Quiq::Path->write($file,'');
# Existenter Pfad
$mtime = Quiq::Path->mtime($file);
$self->ok($mtime > 0);
$self->ok($mtime >= $time);
# mtime setzen
Quiq::Path->mtime($file,$time-3600);
$mtime = Quiq::Path->mtime($file);
$self->is($mtime,$time-3600);
Quiq::Path->delete($file);
}
# -----------------------------------------------------------------------------
sub test_newer : Test(2) {
my $self = shift;
my $file1 = '/tmp/newer_1.txt';
Quiq::Path->write($file1,'');
my $file2 = '/tmp/newer_2.txt';
Quiq::Path->write($file2,'');
Quiq::Path->mtime($file2,time-10);
my $bool = Quiq::Path->newer($file1,$file2);
$self->is($bool,1);
$bool = Quiq::Path->newer($file2,$file1);
$self->is($bool,0);
Quiq::Path->delete($file1);
Quiq::Path->delete($file2);
}
# -----------------------------------------------------------------------------
sub test_newExtension : Test(3) {
my $self = shift;
my $path = '/this/is/a/file.sql';
$path = Quiq::Path->newExtension($path,'.log');
$self->is($path,'/this/is/a/file.log');
$path = '/this/is/a/file.sql';
$path = Quiq::Path->newExtension($path,'log');
$self->is($path,'/this/is/a/file.log');
$path = '/this/is/a/file.ext.sql';
$path = Quiq::Path->newExtension($path,'log');
$self->is($path,'/this/is/a/file.ext.log');
}
# -----------------------------------------------------------------------------
sub test_removeExtension : Test(3) {
my $self = shift;
my $base = Quiq::Path->removeExtension('datei');
$self->is($base,'datei');
$base = Quiq::Path->removeExtension('datei.ext');
$self->is($base,'datei');
$base = Quiq::Path->removeExtension('/ein/pfad/datei.ext');
$self->is($base,'/ein/pfad/datei');
}
# -----------------------------------------------------------------------------
sub test_rename : Test(1) {
my $self = shift;
my $newName = "/tmp/x$$.test";
my $file = "/tmp/rename$$.test";
Quiq::Path->write($file);
Quiq::Path->rename($file,$newName);
$self->ok(-e $newName);
Quiq::Path->delete($newName);
}
sub test_rename_except : Test(1) {
my $self = shift;
my $file = "/tmp/nicht-existent$$";
eval {Quiq::Path->rename($file,'x')};
$self->like($@,qr/PATH-00010/);
}
# -----------------------------------------------------------------------------
sub test_split : Test(30) {
my $self = shift;
my ($dir,$file,$base,$ext,$shortBase,$longExt) =
Quiq::Path->split('datei');
$self->is($dir,'');
$self->is($file,'datei');
$self->is($base,'datei');
$self->is($ext,'');
$self->is($shortBase,'datei');
$self->is($longExt,'');
($dir,$file,$base,$ext,$shortBase,$longExt) =
Quiq::Path->split('datei.ext');
$self->is($dir,'');
$self->is($file,'datei.ext');
$self->is($base,'datei');
$self->is($ext,'ext');
$self->is($shortBase,'datei');
$self->is($longExt,'ext');
($dir,$file,$base,$ext,$shortBase,$longExt) =
Quiq::Path->split('datei.ext1.ext2');
$self->is($dir,'');
$self->is($file,'datei.ext1.ext2');
$self->is($base,'datei.ext1');
$self->is($ext,'ext2');
$self->is($shortBase,'datei');
$self->is($longExt,'ext1.ext2');
($dir,$file,$base,$ext) = Quiq::Path->split('/ein/pfad/datei.ext');
$self->is($dir,'/ein/pfad');
$self->is($file,'datei.ext');
$self->is($base,'datei');
$self->is($ext,'ext');
($dir,$file,$base,$ext,$shortBase,$longExt) =
Quiq::Path->split('/ein/pfad/datei.ext1.ext2');
$self->is($dir,'/ein/pfad');
$self->is($file,'datei.ext1.ext2');
$self->is($base,'datei.ext1');
$self->is($ext,'ext2');
$self->is($shortBase,'datei');
$self->is($longExt,'ext1.ext2');
($dir,undef,$base,undef) = Quiq::Path->split('/ein/pfad/datei.ext');
$self->is($dir,'/ein/pfad');
$self->is($base,'datei');
}
# -----------------------------------------------------------------------------
sub test_symlink : Test(1) {
my $self = shift;
my $symlink = "/tmp/x$$.test";
my $file = "/tmp/symlink$$.test";
Quiq::Path->write($file);
Quiq::Path->symlink($file,$symlink);
$self->ok(-l $symlink);
Quiq::Path->delete($symlink);
Quiq::Path->delete($file);
}
# -----------------------------------------------------------------------------
sub test_symlinkRelative : Test(5) {
my $self = shift;
# FIXME: alle Quiq::Path-Methoden in Quiq::Path implementieren
# und diese nutzen.
my @paths = (
'a' => 'x',
'a' => 'x/y',
'a/b' => 'x',
'a/b' => 'x/y',
'a/b/c' => 'x/y',
);
while (@paths) {
my $path = shift @paths;
my $symlink = shift @paths;
(my $pathTop = $path) =~ s|/.*||;
(my $symlinkTop = $symlink) =~ s|/.*||;
Quiq::Path->delete($pathTop);
Quiq::Path->delete($symlinkTop);
if ($path =~ m|/|) {
# my $pathParent = Quiq::Path->parent($path);
# Quiq::Path->mkdir($pathParent,-recursive=>1);
my $dir = (Quiq::Path->split($path))[0];
Quiq::Path->mkdir($dir,-recursive=>1);
}
if ($symlink =~ m|/|) {
# my $pathSymlink = Quiq::Path->parent($symlink);
# Quiq::Path->mkdir($pathSymlink,-recursive=>1);
my $dir = (Quiq::Path->split($symlink))[0];
Quiq::Path->mkdir($dir,-recursive=>1);
}
Quiq::Path->write($path,$$);
Quiq::Path->symlinkRelative($path,$symlink);
my $data = Quiq::Path->read($symlink);
$self->is($data,$$);
}
Quiq::Path->delete('a');
Quiq::Path->delete('x');
}
# -----------------------------------------------------------------------------
sub test_touch : Test(1) {
my $self = shift;
my $p = Quiq::Path->new;
my $file = $p->tempFile;
my $time1 = time-1;
$p->mtime($file,$time1);
$p->touch($file);
my $time2 = $p->mtime($file);
$self->cmpOk($time1,'<',$time2);
}
# -----------------------------------------------------------------------------
sub test_uid : Test(1) {
my $self = shift;
my $p = Quiq::Path->new;
my $file = $p->tempFile;
my $uid = $p->uid($file);
$self->is($uid,$<);
}
# -----------------------------------------------------------------------------
package main;
Quiq::Path::Test->runTests;
# eof