class TestCase::Sys {
use Sys;
use Sys::IO;
use Sys::OS;
use Sys::IO::Constant as IO;
use Sys::Ioctl::Constant as IOCTL;
use Sys::Socket::Constant as SOCKET;
use Fn;
use Errno;
our $TEST_DIR : rw string;
our $TEST_TMP_DIR : rw cache string;
static method TEST_DIR_FTEST : string () { return "$TEST_DIR/ftest"; }
static method open : int () {
my $test_dir_ftest = &TEST_DIR_FTEST;
my $file = "$test_dir_ftest/file_empty.txt";
{
Sys->open(my $_ = [(Sys::IO::FileStream)undef], "<", $file);
my $stream = $_->[0];
unless ($stream) {
return 0;
}
if (Sys::OS->is_windows) {
warn "[Test Skip]open:FD_CLOEXEC";
}
else {
my $value = Sys->fcntl(Sys->fileno($stream), IO->F_GETFD, IO->FD_CLOEXEC);
unless ($value) {
return 0;
}
}
}
return 1;
}
static method sysopen : int () {
my $test_dir_ftest = &TEST_DIR_FTEST;
{
my $file = "$test_dir_ftest/file_empty.txt";
my $fd = -1;
Sys->sysopen(\$fd, $file, IO->O_RDONLY, 0644);
if (Sys::OS->is_windows) {
warn "[Test Skip]sysopen:FD_CLOEXEC";
}
else {
my $value = Sys->fcntl($fd, IO->F_GETFD, IO->FD_CLOEXEC);
unless ($value) {
return 0;
}
}
Sys::IO->close($fd);
}
{
my $file = "$TEST_TMP_DIR/create_no_perms.txt";
my $fd = -1;
Sys->sysopen(\$fd, $file, IO->O_WRONLY|IO->O_CREAT);
Sys::IO->close($fd);
}
return 1;
}
static method socket : int () {
{
my $socket = -1;
Sys->socket(\$socket, SOCKET->AF_INET, SOCKET->SOCK_STREAM, 0);
unless ($socket > 0) {
return 0;
}
if (Sys::OS->is_windows) {
warn "[Test Skip]socket:FD_CLOEXEC";
}
else {
my $value = Sys->fcntl($socket, IO->F_GETFD, IO->FD_CLOEXEC);
unless ($value) {
return 0;
}
}
}
return 1;
}
static method pipe : int () {
{
my $write_fd = -1;
my $read_fd = -1;
Sys->pipe(\$write_fd, \$read_fd);
unless ($write_fd > 0) {
return 0;
}
unless ($read_fd > 0) {
return 0;
}
if (Sys::OS->is_windows) {
warn "[Test Skip]pipe:FD_CLOEXEC:write_fd";
}
else {
my $value = Sys->fcntl($write_fd, IO->F_GETFD, IO->FD_CLOEXEC);
if ($value) {
return 0;
}
}
if (Sys::OS->is_windows) {
warn "[Test Skip]pipe:FD_CLOEXEC:read_fd";
}
else {
my $value = Sys->fcntl($read_fd, IO->F_GETFD, IO->FD_CLOEXEC);
if ($value) {
return 0;
}
}
unless (Sys::OS->is_windows) {
my $flag0 = Sys->fcntl($write_fd, IO->F_GETFD);
if ($flag0 & IO->FD_CLOEXEC) {
return 0;
}
my $flag1 = Sys->fcntl($read_fd, IO->F_GETFD);
if ($flag1 & IO->FD_CLOEXEC) {
return 0;
}
}
}
return 1;
}
static method A : int () {
{
{
my $file = "t/ftest/file_empty.txt";
my $atime = Sys->A($file);
warn "[Test Output]Sys->A:$atime";
unless ($atime > 0) {
return 0;
}
}
}
# Excetpions
{
{
my $file = "t/ftest/file_not_exists.txt";
eval { Sys->A($file); }
unless ($@) {
return 0;
}
}
}
return 1;
}
static method C : int () {
{
{
my $file = "t/ftest/file_empty.txt";
my $ctime = Sys->C($file);
warn "[Test Output]Sys->C:$ctime";
unless ($ctime > 0) {
return 0;
}
}
}
# Excetpions
{
{
my $file = "t/ftest/file_not_exists.txt";
eval { Sys->C($file); }
unless ($@) {
return 0;
}
}
}
return 1;
}
static method M : int () {
{
{
my $file = "t/ftest/file_empty.txt";
my $mtime = Sys->M($file);
warn "[Test Output]Sys->M:$mtime";
unless ($mtime > 0) {
return 0;
}
}
}
# Excetpions
{
{
my $file = "t/ftest/file_not_exists.txt";
eval { Sys->M($file); }
unless ($@) {
return 0;
}
}
}
return 1;
}
static method O : int () {
{
{
my $file = "t/ftest/file_empty.txt";
my $ok = Sys->O($file);
warn("[Test Output]Sys->O:$ok");
}
}
{
{
my $file = "t/ftest/file_not_exists.txt";
Errno->set_errno(0);
my $ok = Sys->O($file);
unless ($ok == 0) {
return 0;
}
unless (Errno->errno > 0) {
return 0;
}
}
}
return 1;
}
static method R : int () {
{
{
my $file = "t/ftest/file_empty.txt";
my $ok = Sys->R($file);
unless ($ok == 1) {
return 0;
}
}
}
{
{
my $file = "t/ftest/file_not_exists.txt";
Errno->set_errno(0);
my $ok = Sys->R($file);
unless ($ok == 0) {
return 0;
}
unless (Errno->errno > 0) {
return 0;
}
}
}
return 1;
}
static method S : int () {
{
{
my $file = "t/ftest/file_empty.txt";
my $ok = Sys->S($file);
if ($ok) {
return 0;
}
}
}
{
{
my $file = "t/ftest/file_not_exists.txt";
Errno->set_errno(0);
my $ok = Sys->S($file);
unless ($ok == 0) {
return 0;
}
unless (Errno->errno > 0) {
return 0;
}
}
}
{
my $socket = Sys::Socket->socket(SOCKET->AF_UNIX, SOCKET->SOCK_STREAM, 0);
Fn->defer([$socket : int] method :void () {
Sys::Socket->close($socket);
});
my $socket_file = "$TEST_TMP_DIR/S_socket";
my $sockaddr = Sys::Socket::Sockaddr::Un->new;
$sockaddr->set_sun_family(SOCKET->AF_UNIX);
$sockaddr->set_sun_path($socket_file);
Sys->bind($socket, $sockaddr);
my $ok = Sys->S($socket_file);
unless ($ok) {
return 0;
}
}
return 1;
}
static method W : int () {
{
{
my $file = "t/ftest/file_empty.txt";
my $ok = Sys->W($file);
unless ($ok == 1) {
return 0;
}
}
}
{
{
my $file = "t/ftest/file_not_exists.txt";
Errno->set_errno(0);
my $ok = Sys->W($file);
unless ($ok == 0) {
return 0;
}
unless (Errno->errno > 0) {
return 0;
}
}
}
return 1;
}
static method X : int () {
{
{
my $file = "t/ftest/myexe.exe";
my $ok = Sys->X($file);
unless ($ok == 1) {
return 0;
}
}
}
{
{
my $file = "t/ftest/myexe.bat";
my $ok = Sys->X($file);
unless ($ok == 1) {
return 0;
}
}
}
{
{
my $file = "t/ftest/file_empty.txt";
my $ok = Sys->X($file);
unless ($ok == 0) {
return 0;
}
}
}
{
{
my $file = "t/ftest/file_not_exists.txt";
Errno->set_errno(0);
my $ok = Sys->X($file);
unless ($ok == 0) {
return 0;
}
unless (Errno->errno > 0) {
return 0;
}
}
}
return 1;
}
static method b : int () {
{
{
my $file = "t/ftest/file_empty.txt";
my $ok = Sys->b($file);
}
}
{
{
my $file = "t/ftest/file_not_exists.txt";
Errno->set_errno(0);
my $ok = Sys->b($file);
unless ($ok == 0) {
return 0;
}
unless (Errno->errno > 0) {
return 0;
}
}
}
return 1;
}
static method d : int () {
{
{
my $file = "t/ftest/file_empty.txt";
my $ok = Sys->d($file);
unless ($ok == 0) {
return 0;
}
}
{
my $file = "t/ftest/dir_empty";
my $ok = Sys->d($file);
unless ($ok == 1) {
return 0;
}
}
}
{
{
my $file = "t/ftest/file_not_exists.txt";
Errno->set_errno(0);
my $ok = Sys->d($file);
unless ($ok == 0) {
return 0;
}
unless (Errno->errno > 0) {
return 0;
}
}
}
return 1;
}
static method e : int () {
{
{
my $file = "t/ftest/file_empty.txt";
my $ok = Sys->e($file);
unless ($ok == 1) {
return 0;
}
}
{
my $file = "t/ftest/dir_empty";
my $ok = Sys->e($file);
unless ($ok == 1) {
return 0;
}
}
}
{
{
my $file = "t/ftest/file_not_exists.txt";
Errno->set_errno(0);
my $ok = Sys->e($file);
unless ($ok == 0) {
return 0;
}
unless (Errno->errno > 0) {
return 0;
}
}
}
return 1;
}
static method f : int () {
{
{
my $file = "t/ftest/not_found_file";
my $ok = Sys->f($file);
unless ($ok == 0) {
return 0;
}
}
{
my $file = "t/ftest/file_empty.txt";
my $ok = Sys->f($file);
unless ($ok == 1) {
return 0;
}
}
{
my $file = "t/ftest/dir_empty";
my $ok = Sys->f($file);
unless ($ok == 0) {
return 0;
}
}
}
{
{
my $file = "t/ftest/file_not_exists.txt";
Errno->set_errno(0);
my $ok = Sys->f($file);
unless ($ok == 0) {
return 0;
}
unless (Errno->errno > 0) {
return 0;
}
}
}
return 1;
}
static method g : int () {
{
{
my $file = "t/ftest/file_empty.txt";
my $ok = Sys->g($file);
}
}
{
{
my $file = "t/ftest/file_not_exists.txt";
Errno->set_errno(0);
my $ok = Sys->g($file);
unless ($ok == 0) {
return 0;
}
unless (Errno->errno > 0) {
return 0;
}
}
}
return 1;
}
static method k : int () {
{
{
my $file = "t/ftest/file_empty.txt";
my $ok = Sys->k($file);
}
}
{
{
my $file = "t/ftest/file_not_exists.txt";
Errno->set_errno(0);
my $ok = Sys->k($file);
unless ($ok == 0) {
return 0;
}
unless (Errno->errno > 0) {
return 0;
}
}
}
return 1;
}
static method l : int () {
{
# File
{
my $file = "t/ftest/file_empty.txt";
my $ok = Sys->l($file);
}
}
{
{
my $file = "t/ftest/file_not_exists.txt";
Errno->set_errno(0);
my $ok = Sys->l($file);
unless ($ok == 0) {
return 0;
}
unless (Errno->errno > 0) {
return 0;
}
}
}
return 1;
}
static method o : int () {
{
# File
{
my $file = "t/ftest/file_empty.txt";
my $ok = Sys->o($file);
}
}
{
{
my $file = "t/ftest/file_not_exists.txt";
Errno->set_errno(0);
my $ok = Sys->o($file);
unless ($ok == 0) {
return 0;
}
unless (Errno->errno > 0) {
return 0;
}
}
}
return 1;
}
static method p : int () {
{
{
my $file = "t/ftest/file_empty.txt";
my $ok = Sys->p($file);
}
}
{
{
my $file = "t/ftest/file_not_exists.txt";
Errno->set_errno(0);
my $ok = Sys->p($file);
unless ($ok == 0) {
return 0;
}
unless (Errno->errno > 0) {
return 0;
}
}
}
return 1;
}
static method r : int () {
{
{
my $file = "t/ftest/file_empty.txt";
my $ok = Sys->r($file);
unless ($ok == 1) {
return 0;
}
}
}
{
{
my $file = "t/ftest/file_not_exists.txt";
Errno->set_errno(0);
my $ok = Sys->r($file);
unless ($ok == 0) {
return 0;
}
unless (Errno->errno > 0) {
return 0;
}
}
}
return 1;
}
static method s : int () {
{
{
my $file = "t/ftest/file_empty.txt";
my $size = Sys->s($file);
unless ($size == 0) {
return 0;
}
}
}
# Excetpions
{
{
my $file = "t/ftest/file_not_exists.txt";
eval { Sys->s($file); }
unless ($@) {
return 0;
}
}
}
return 1;
}
static method u : int () {
{
# File
{
my $file = "t/ftest/file_empty.txt";
my $ok = Sys->u($file);
}
}
{
{
my $file = "t/ftest/file_not_exists.txt";
Errno->set_errno(0);
my $ok = Sys->u($file);
unless ($ok == 0) {
return 0;
}
unless (Errno->errno > 0) {
return 0;
}
}
}
return 1;
}
static method w : int () {
{
{
my $file = "t/ftest/file_empty.txt";
my $ok = Sys->w($file);
unless ($ok == 1) {
return 0;
}
}
}
{
{
my $file = "t/ftest/file_not_exists.txt";
Errno->set_errno(0);
my $ok = Sys->w($file);
unless ($ok == 0) {
return 0;
}
unless (Errno->errno > 0) {
return 0;
}
}
}
return 1;
}
static method x : int () {
{
{
my $file = "t/ftest/myexe.exe";
my $ok = Sys->x($file);
unless ($ok == 1) {
return 0;
}
}
}
{
{
my $file = "t/ftest/myexe.bat";
my $ok = Sys->x($file);
unless ($ok == 1) {
return 0;
}
}
}
{
{
my $file = "t/ftest/file_empty.txt";
my $ok = Sys->x($file);
unless ($ok == 0) {
return 0;
}
}
}
{
{
my $file = "t/ftest/file_not_exists.txt";
Errno->set_errno(0);
my $ok = Sys->x($file);
unless ($ok == 0) {
return 0;
}
unless (Errno->errno > 0) {
return 0;
}
}
}
return 1;
}
static method z : int () {
{
# File
{
my $file = "t/ftest/file_empty.txt";
my $non_zero = Sys->z($file);
unless ($non_zero) {
return 0;
}
}
}
# Excetpions
{
{
my $file = "t/ftest/file_not_exists.txt";
eval { Sys->z($file); }
unless ($@) {
return 0;
}
}
}
return 1;
}
static method readlink : int ($test_dir : string) {
my $sep = (string)undef;
if (Sys::OS->is_windows) {
$sep = "\\";
}
else {
$sep = "/";
}
my $file = "$test_dir${sep}foo.txt";
{
Sys->open(my $_ = [(Sys::IO::FileStream)undef], ">", $file);
my $stream = $_->[0];
unless ($stream) {
return 0;
}
Sys->close($stream);
}
my $file_symlink = "$test_dir${sep}foo_link";
{
Sys->symlink($file, $file_symlink);
my $exists_symlink_file = Sys->l($file_symlink);
unless ($exists_symlink_file) {
return 0;
}
}
{
my $ret_file = Sys->readlink($file_symlink);
unless ($ret_file eq $file) {
return 0;
}
}
{
my $file = "t/ftest/file_empty.txt";
eval { Sys->readlink($file); }
unless ($@) {
return 0;
}
}
{
my $file = "t/ftest/not_found_file";
eval { Sys->readlink($file); }
unless ($@) {
return 0;
}
}
return 1;
}
static method mkdir : int ($test_dir : string) {
my $dir = "$test_dir/foo";
Sys->mkdir($dir, 0755);
unless (Sys->d($dir)) {
return 0;
}
{
my $dir = "$test_dir/foo_no_mode";
Sys->mkdir($dir);
unless (Sys->d($dir)) {
return 0;
}
}
{
eval { Sys->mkdir($dir, 0755); };
unless (Fn->contains($@, "foo")) {
return 0;
}
}
my $test_tmp_dir = &TEST_TMP_DIR;
{
my $dir = "$test_tmp_dir/mkdir_あ";
Sys->mkdir($dir);
}
return 1;
}
static method umask : int ($test_dir : string) {
my $dir = "$test_dir/foo";
my $old_mask = Sys->umask(IO->S_IRUSR);
my $cur_mask = Sys->umask(IO->S_IWUSR);
unless ($cur_mask == IO->S_IRUSR) {
return 0;
}
# Restore
Sys->umask($old_mask);
{
unless (Sys->umask == $old_mask) {
return 0;
}
}
return 1;
}
static method rmdir : int ($test_dir : string) {
my $dir = "$test_dir/foo";
Sys->mkdir($dir, 0755);
unless (Sys->d($dir)) {
return 0;
}
Sys->rmdir($dir);
if (Sys->e($dir)) {
return 0;
}
{
eval { Sys->rmdir($dir); };
unless (Fn->contains($@, "foo")) {
return 0;
}
}
my $test_tmp_dir = &TEST_TMP_DIR;
{
my $dir = "$test_tmp_dir/rmdir_あ";
Sys->mkdir($dir);
Sys->rmdir($dir);
}
return 1;
}
static method chdir : int ($test_dir : string) {
my $dir = "$test_dir/ftest/dir_empty";
{
my $cwd_save = Sys::IO->getcwd(undef, 0);
Fn->defer([$cwd_save : string]method : void () {
Sys->chdir($cwd_save);
});
Sys->chdir($dir);
my $cwd = Sys::IO->getcwd(undef, 0);
unless (Fn->contains($cwd, "dir_empty")) {
return 0;
}
}
{
eval { Sys->chdir("$dir/not_found.txt"); };
unless (Fn->contains($@, "not_found.txt")) {
return 0;
}
}
{
my $dir = "$TEST_TMP_DIR/chdir_あ";
Sys->mkdir($dir);
my $cwd_save = Sys::IO->getcwd(undef, 0);
Fn->defer([$cwd_save : string]method : void () {
Sys->chdir($cwd_save);
});
Sys->chdir($dir);
}
return 1;
}
static method chmod : int ($test_dir : string) {
{
my $file = "$test_dir/foo.txt";
Sys->open(my $_ = [(Sys::IO::FileStream)undef], ">", $file);
my $stream = $_->[0];
unless (Sys->f($file)) {
return 0;
}
Sys->close($stream);
Sys->chmod(0755, $file);
{
eval { Sys->chmod(0755, "$file/not_found.txt"); };
unless (Fn->contains($@, "not_found.txt")) {
return 0;
}
}
}
{
my $file = "$test_dir/open_あ.txt";
Sys->open(my $_ = [(Sys::IO::FileStream)undef], ">", $file);
my $stream = $_->[0];
Sys->close($stream);
Sys->chmod(0755, $file);
}
return 1;
}
static method unlink : int ($test_dir : string) {
my $file = "$test_dir/foo.txt";
{
Sys->open([(Sys::IO::FileStream)undef], ">", $file);
}
unless (Sys->f($file)) {
return 0;
}
Sys->unlink($file);
if (Sys->e($file)) {
return 0;
}
{
eval { Sys->unlink($file); };
unless (Fn->contains($@, "foo.txt")) {
return 0;
}
}
{
my $file = "$TEST_TMP_DIR/unlink_あ.txt";
Sys->open(my $_ = [(Sys::IO::FileStream)undef], ">", $file);
my $fh = $_->[0];
Sys->close($fh);
Sys->unlink($file);
}
return 1;
}
static method rename : int ($test_dir : string) {
{
my $file = "$test_dir/foo.txt";
{
Sys->open([(Sys::IO::FileStream)undef], ">", $file);
}
unless (Sys->e($file)) {
return 0;
}
my $new_file = "$test_dir/foo_new.txt";
Sys->rename($file, $new_file);
if (Sys->e($file)) {
return 0;
}
unless (Sys->e($new_file)) {
return 0;
}
}
{
my $file = "$test_dir/foo.txt";
my $new_file = "$test_dir/foo_new.txt";
eval { Sys->rename($file, $new_file); };
unless (Fn->contains($@, "foo.txt")) {
return 0;
}
unless (Fn->contains($@, "foo_new.txt")) {
return 0;
}
}
{
my $file_from = "$TEST_TMP_DIR/rename_あ.txt";
my $file_to = "$TEST_TMP_DIR/rename_い.txt";
Sys->open(my $_ = [(Sys::IO::FileStream)undef], ">", $file_from);
my $fh = $_->[0];
Sys->close($fh);
Sys->rename($file_from, $file_to);
if (Sys->e($file_from)) {
return 0;
}
unless (Sys->e($file_to)) {
return 0;
}
}
# Same name
{
my $file_from = "$TEST_TMP_DIR/rename_same_name.txt";
my $file_to = $file_from;
Sys->open(my $_ = [(Sys::IO::FileStream)undef], ">", $file_from);
my $fh = $_->[0];
Sys->close($fh);
Sys->rename($file_from, $file_to);
unless (Sys->e($file_from)) {
return 0;
}
}
# Overwrite
{
my $file_from = "$TEST_TMP_DIR/rename_overwrite_from.txt";
my $file_to = "$TEST_TMP_DIR/rename_overwrite_to.txt";
{
Sys->open([(Sys::IO::FileStream)undef], ">", $file_from);
}
{
Sys->open([(Sys::IO::FileStream)undef], ">", $file_to);
}
Sys->rename($file_from, $file_to);
if (Sys->e($file_from)) {
return 0;
}
unless (Sys->e($file_to)) {
return 0;
}
}
return 1;
}
static method ioctl : int () {
# Socket
my $socket = Sys::Socket->socket(SOCKET->AF_INET, SOCKET->SOCK_STREAM, 0);
unless ($socket> 0) {
return 0;
}
Fn->defer([$socket : int] method :void () {
Sys::Socket->close($socket);
});
my $value_ref = [1];
my $status_ioctl = 0;
eval { $status_ioctl = Sys->ioctl($socket, IOCTL->FIONBIO, $value_ref); };
if (Sys::OS->is_windows) {
unless ($status_ioctl == 0) {
return 0;
}
}
else {
if ($@) {
warn "[Test Output]$@";
}
else {
unless ($status_ioctl == 0) {
return 0;
}
}
}
return 1;
}
static method env : int () {
{
Sys->set_env("NAME", "VALUE");
my $value = Sys->env("NAME");
unless ($value eq "VALUE") {
return 0;
}
}
{
Sys->set_env("NAME", "");
my $value = Sys->env("NAME");
if ($value) {
return 0;
}
}
{
Sys->set_env("NAME", undef);
my $value = Sys->env("NAME");
if ($value) {
return 0;
}
}
# Excetpion
{
eval { Sys->set_env(undef, "VALUE"); }
unless ($@) {
return 0;
}
}
return 1;
}
static method set_env : int () {
return &env;
}
static method opendir : int () {
my $test_dir = &TEST_DIR;
my $test_dir_ftest = &TEST_DIR_FTEST;
{
my $dir_stream_ref = [(Sys::IO::DirStream)undef];
Sys->opendir($dir_stream_ref, $test_dir_ftest);
my $dir_stream = $dir_stream_ref->[0];
unless ($dir_stream) {
return 0;
}
}
return 1;
}
static method readdir : int () {
my $test_dir_ftest = &TEST_DIR_FTEST;
{
my $dir_stream_ref = [(Sys::IO::DirStream)undef];
Sys->opendir($dir_stream_ref, $test_dir_ftest);
my $dir_stream = $dir_stream_ref->[0];
Fn->defer([$dir_stream : Sys::IO::DirStream] method : void () {
Sys->closedir($dir_stream);
});
unless ($dir_stream) {
return 0;
}
Sys->rewinddir($dir_stream);
Sys->rewinddir($dir_stream);
{
my $current_offset = Sys->telldir($dir_stream);
unless ($current_offset == 0) {
return 0;
}
}
{
my $current_offset = Sys->telldir($dir_stream);
unless ($current_offset == 0) {
return 0;
}
}
my $check_file_count = 0;
while (my $name = Sys->readdir($dir_stream)) {
if ($name eq "foo.txt") {
$check_file_count++;
}
elsif ($name eq "bar.txt") {
$check_file_count++;
}
}
unless ($check_file_count == 2) {
return 0;
}
}
return 1;
}
static method seekdir : int () {
my $test_dir_ftest = &TEST_DIR_FTEST;
{
my $dir_stream_ref = [(Sys::IO::DirStream)undef];
Sys->opendir($dir_stream_ref, $test_dir_ftest);
my $dir_stream = $dir_stream_ref->[0];
my $name = Sys->readdir($dir_stream);
my $offset = Sys->telldir($dir_stream);
my $name_next = Sys->readdir($dir_stream);
Sys->seekdir($dir_stream, $offset);
my $name2 = Sys->readdir($dir_stream);
unless ($name) {
warn;
return 0;
}
unless ($name2) {
warn;
return 0;
}
unless ($name2 eq $name_next) {
warn;
return 0;
}
}
return 1;
}
static method telldir : int () {
my $test_dir_ftest = &TEST_DIR_FTEST;
{
my $dir_stream_ref = [(Sys::IO::DirStream)undef];
Sys->opendir($dir_stream_ref, $test_dir_ftest);
my $dir_stream = $dir_stream_ref->[0];
my $name = Sys->readdir($dir_stream);
my $offset = Sys->telldir($dir_stream);
my $name_next = Sys->readdir($dir_stream);
Sys->seekdir($dir_stream, $offset);
my $name2 = Sys->readdir($dir_stream);
unless ($name) {
warn;
return 0;
}
unless ($name2) {
warn;
return 0;
}
unless ($name2 eq $name_next) {
warn;
return 0;
}
}
return 1;
}
static method rewinddir : int () {
my $test_dir_ftest = &TEST_DIR_FTEST;
{
my $dir_stream_ref = [(Sys::IO::DirStream)undef];
Sys->opendir($dir_stream_ref, $test_dir_ftest);
my $dir_stream = $dir_stream_ref->[0];
my $name = Sys->readdir($dir_stream);
Sys->rewinddir($dir_stream);
my $name2 = Sys->readdir($dir_stream);
unless ($name) {
return 0;
}
unless ($name2) {
return 0;
}
unless ($name2 eq $name) {
return 0;
}
}
return 1;
}
static method closedir : int () {
my $test_dir_ftest = &TEST_DIR_FTEST;
{
my $dir_stream_ref = [(Sys::IO::DirStream)undef];
Sys->opendir($dir_stream_ref, $test_dir_ftest);
my $dir_stream = $dir_stream_ref->[0];
unless ($dir_stream) {
return 0;
}
if ($dir_stream->closed) {
warn $dir_stream->closed;
return 0;
}
Sys->closedir($dir_stream);
unless ($dir_stream->closed) {
warn $dir_stream->closed;
return 0;
}
}
return 1;
}
# rand (srand is called from rand)
static method rand : int () {
# 0 <= random_number < 1
{
my $rand = 0.0;
my $invalid_range = 0;
for (my $i = 0; $i < 100000; $i++) {
$rand = Sys->rand;
unless ($rand >= 0 && $rand < 1) {
$invalid_range = 1;
last;
}
}
if ($invalid_range) {
return 0;
}
}
# Apper random numbers
{
my $founds_plus = new int[10];
my $founds_minus = new int[10];
my $rand = 0.0;
for (my $i = 0; $i < 100000; $i++) {
$rand = Sys->rand;
# 0-9
my $dig0 = (int)($rand * 10);
$founds_plus->[$dig0] = 1;
}
unless (Array->equals_int($founds_plus, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1])) {
return 0;
}
}
# Apper random numbers
{
my $founds_plus = new int[10];
my $founds_minus = new int[10];
my $rand = 0.0;
for (my $i = 0; $i < 100000; $i++) {
$rand = Sys->rand(10);
# 0-9
my $dig0 = (int)($rand);
$founds_plus->[$dig0] = 1;
}
unless (Array->equals_int($founds_plus, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1])) {
return 0;
}
}
return 1;
}
static method set_tcp_keepalive : int () {
# Create a TCP socket for testing
my $domain = Sys::Socket::Constant->AF_INET;
my $type = Sys::Socket::Constant->SOCK_STREAM;
my $protocol = 0;
my $socket_fd = Sys::Socket->socket($domain, $type, $protocol);
if ($socket_fd < 0) {
warn "Failed to create socket for testing";
return 0;
}
# Ensure socket is closed at the end
Fn->defer([$socket_fd : int] method : void () {
Sys::Socket->close($socket_fd);
});
# --- Case 1: Default behavior (Interval omitted) ---
{
my $onoff = 1;
my $idle_setting = 123;
# Set values (Interval is omitted, should default to 123)
Sys->set_tcp_keepalive($socket_fd, $onoff, $idle_setting);
# Verify SO_KEEPALIVE (All platforms)
my $onoff_binary = Sys->getsockopt($socket_fd, Sys::Socket::Constant->SOL_SOCKET, Sys::Socket::Constant->SO_KEEPALIVE);
my $onoff_got = Fn->unpack("l", $onoff_binary)->[0]->(int);
unless ($onoff ? $onoff_got != 0 : $onoff_got == 0) {
diag "SO_KEEPALIVE mismatch (Case 1): expected $onoff, but got $onoff_got";
return 0;
}
# Verify Time settings (Skip on Windows)
unless (Sys::OS->is_windows) {
my $level = Sys::Socket::Constant->IPPROTO_TCP;
# IDLE
my $idle_opt = Sys::OS->defined("__APPLE__") ? Sys::Socket::Constant->TCP_KEEPALIVE : Sys::Socket::Constant->TCP_KEEPIDLE;
my $idle_got = Fn->unpack("l", Sys->getsockopt($socket_fd, $level, $idle_opt))->[0]->(int);
unless ($idle_got == $idle_setting) {
diag "TCP keep-idle mismatch (Case 1): expected $idle_setting, but got $idle_got";
return 0;
}
# INTVL (Should match IDLE)
my $intvl_got = Fn->unpack("l", Sys->getsockopt($socket_fd, $level, Sys::Socket::Constant->TCP_KEEPINTVL))->[0]->(int);
unless ($intvl_got == $idle_setting) {
diag "TCP keep-intvl mismatch (Case 1): expected $idle_setting, but got $intvl_got";
return 0;
}
}
}
# --- Case 2: Custom interval behavior ---
{
my $onoff = 1;
my $idle_setting = 100;
my $intvl_setting = 50;
# Set values explicitly
Sys->set_tcp_keepalive($socket_fd, $onoff, $idle_setting, $intvl_setting);
# Verify SO_KEEPALIVE (All platforms)
my $onoff_binary = Sys->getsockopt($socket_fd, Sys::Socket::Constant->SOL_SOCKET, Sys::Socket::Constant->SO_KEEPALIVE);
my $onoff_got = Fn->unpack("l", $onoff_binary)->[0]->(int);
unless ($onoff ? $onoff_got != 0 : $onoff_got == 0) {
diag "SO_KEEPALIVE mismatch (Case 2): expected $onoff, but got $onoff_got";
return 0;
}
# Verify Time settings (Skip on Windows)
unless (Sys::OS->is_windows) {
my $level = Sys::Socket::Constant->IPPROTO_TCP;
# IDLE
my $idle_opt = Sys::OS->defined("__APPLE__") ? Sys::Socket::Constant->TCP_KEEPALIVE : Sys::Socket::Constant->TCP_KEEPIDLE;
my $idle_got = Fn->unpack("l", Sys->getsockopt($socket_fd, $level, $idle_opt))->[0]->(int);
unless ($idle_got == $idle_setting) {
diag "TCP keep-idle mismatch (Case 2): expected $idle_setting, but got $idle_got";
return 0;
}
# INTVL (Should match explicit setting)
my $intvl_got = Fn->unpack("l", Sys->getsockopt($socket_fd, $level, Sys::Socket::Constant->TCP_KEEPINTVL))->[0]->(int);
unless ($intvl_got == $intvl_setting) {
diag "TCP keep-intvl mismatch (Case 2): expected $intvl_setting, but got $intvl_got";
return 0;
}
}
}
return 1;
}
}