class TestCase::Sys::IO {
  use Sys::IO;
  use Sys::IO::Constant as IO;
  use Fn;
  use Sys::IO::Stat;
  use Sys;
  use Sys::Time;
  use Sys::IO::Flock;
  
  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 ($tmp_dir : string) {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_empty.txt";
      my $fd = Sys::IO->open($file, IO->O_RDONLY, 0644);
      
      unless ($fd >= 0) {
        return 0;
      }
      Sys::IO->close($fd);
    }
    
    {
      my $file = "$test_dir_ftest/not_found.txt";
      eval { Sys::IO->open($file, IO->O_RDWR, 0644); };
      
      unless ($@) {
        return 0;
      }
      
      unless (Fn->contains($@, "not_found.txt")) {
        return 0;
      }
      
      unless (eval_error_id == basic_type_id Error::System) {
        return 0;
      }
    }
    
    {
      my $file = "$tmp_dir/foo.txt";
      my $fd = Sys::IO->open($file, IO->O_WRONLY | IO->O_CREAT, IO->S_IRUSR | IO->S_IWUSR | IO->S_IRGRP | IO->S_IWGRP | IO->S_IROTH | IO->S_IWOTH);
      
      unless ($fd >= 0) {
        return 0;
      }
      Sys::IO->close($fd);
    }
    
    {
      my $file = "$tmp_dir/open_あいうえお.txt";
      my $fd = Sys::IO->open($file, IO->O_WRONLY | IO->O_CREAT, IO->S_IRUSR | IO->S_IWUSR | IO->S_IRGRP | IO->S_IWGRP | IO->S_IROTH | IO->S_IWOTH);
      
      unless ($fd >= 0) {
        return 0;
      }
      Sys::IO->close($fd);
    }
    
    IO->O_ACCMODE;
    
    return 1;
  }

  static method read : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $fd = Sys::IO->open($file, IO->O_RDONLY);
      
      unless ($fd >= 0) {
        return 0;
      }

      my $buffer = (mutable string)new_string_len 4;
      my $count = 4;
      
      my $read_length = 0;
      
      $read_length = Sys::IO->read($fd, $buffer, $count);
      
      unless ($buffer eq "abcd") {
        return 0;
      }
      
      unless ($read_length == 4) {
        return 0;
      }

      $read_length = Sys::IO->read($fd, $buffer, $count);
      
      unless ($buffer eq "efgh") {
        return 0;
      }
      
      unless ($read_length == 4) {
        return 0;
      }

      $read_length = Sys::IO->read($fd, $buffer, $count);
      
      unless ($read_length == 0) {
        return 0;
      }
      Sys::IO->close($fd);
    }
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $fd = Sys::IO->open($file, IO->O_RDONLY);
      
      unless ($fd >= 0) {
        return 0;
      }

      my $buffer = (mutable string)new_string_len 4;
      my $count = 4;
      
      my $read_length = 0;
      
      $read_length = Sys->sysread($fd, $buffer, $count);
      
      unless ($buffer eq "abcd") {
        return 0;
      }
      
      unless ($read_length == 4) {
        return 0;
      }

      $read_length = Sys->sysread($fd, $buffer, $count);
      
      unless ($buffer eq "efgh") {
        return 0;
      }
      
      unless ($read_length == 4) {
        return 0;
      }

      $read_length = Sys->sysread($fd, $buffer, $count);
      
      unless ($read_length == 0) {
        return 0;
      }
      Sys::IO->close($fd);
    }
    
    return 1;
  }

  static method write : int ($tmp_dir : string) {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$tmp_dir/foo.txt";
      my $fd = Sys::IO->open($file, IO->O_WRONLY | IO->O_CREAT, 0666);
      
      unless ($fd >= 0) {
        return 0;
      }

      my $write_length = 0;
      $write_length = Sys::IO->write($fd, "abcd", 4);
      unless ($write_length == 4) {
        return 0;
      }
      
      $write_length = Sys::IO->write($fd, "efgh", 4);
      unless ($write_length == 4) {
        return 0;
      }
      
      Sys::IO->close($fd);
    }
    
    {
      my $file = "$tmp_dir/foo.txt";
      my $fd = Sys::IO->open($file, IO->O_RDONLY);
      
      unless ($fd >= 0) {
        return 0;
      }

      my $buffer = (mutable string)new_string_len 4;
      my $count = 4;
      
      my $read_length = 0;
      
      $read_length = Sys::IO->read($fd, $buffer, $count);
      
      unless ($buffer eq "abcd") {
        return 0;
      }
      
      unless ($read_length == 4) {
        return 0;
      }

      $read_length = Sys::IO->read($fd, $buffer, $count);
      
      unless ($buffer eq "efgh") {
        return 0;
      }
      
      unless ($read_length == 4) {
        return 0;
      }

      $read_length = Sys::IO->read($fd, $buffer, $count);
      
      unless ($read_length == 0) {
        return 0;
      }
      Sys::IO->close($fd);
    }
    
    {
      my $file = "$tmp_dir/foo.txt";
      my $fd = Sys::IO->open($file, IO->O_WRONLY | IO->O_CREAT, 0666);
      
      unless ($fd >= 0) {
        return 0;
      }

      my $write_length = 0;
      $write_length = Sys->syswrite($fd, "abcd", 4);
      unless ($write_length == 4) {
        return 0;
      }
      
      $write_length = Sys->syswrite($fd, "efgh");
      unless ($write_length == 4) {
        return 0;
      }
      
      Sys::IO->close($fd);
    }
    
    return 1;
  }

  static method lseek : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $fd = Sys::IO->open($file, IO->O_RDONLY);
      
      unless ($fd >= 0) {
        return 0;
      }

      my $buffer = (mutable string)new_string_len 4;
      my $count = 4;
      
      my $read_length = 0;
      
      my $cur_offset = Sys::IO->lseek($fd, 4, IO->SEEK_SET);
      
      unless ($cur_offset == 4) {
        return 0;
      }
      
      $read_length = Sys::IO->read($fd, $buffer, $count);
      
      unless ($buffer eq "efgh") {
        return 0;
      }
      
      unless ($read_length == 4) {
        return 0;
      }

      Sys::IO->close($fd);
    }
    
    # The constant values for the seek functions
    {
      IO->SEEK_SET;
      IO->SEEK_CUR;
      IO->SEEK_END;
    }
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $fd = Sys::IO->open($file, IO->O_RDONLY);
      
      unless ($fd >= 0) {
        return 0;
      }

      my $buffer = (mutable string)new_string_len 4;
      my $count = 4;
      
      my $read_length = 0;
      
      my $cur_offset = Sys->sysseek($fd, 4, IO->SEEK_SET);
      
      unless ($cur_offset == 4) {
        return 0;
      }
      
      $read_length = Sys::IO->read($fd, $buffer, $count);
      
      unless ($buffer eq "efgh") {
        return 0;
      }
      
      unless ($read_length == 4) {
        return 0;
      }

      Sys::IO->close($fd);
    }
    return 1;
  }

  static method close : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_empty.txt";
      my $fd = Sys::IO->open($file, IO->O_RDWR, IO->O_TRUNC);
      
      unless ($fd >= 0) {
        return 0;
      }
      
      my $status = Sys::IO->close($fd);
      
      unless ($status == 0) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method fileno : int ($tmp_dir : string) {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    warn;
    
    {
      my $file = "$tmp_dir/foo.txt";
      my $stream = Sys::IO->fopen($file, "w");
    
    warn;
    
      unless (Sys->f($file)) {
        return 0;
      }
    
    warn;
    
      my $fd = Sys::IO->fileno($stream);
    
    warn;
    
      unless ($fd >= 0) {
        return 0;
      }
    
    warn;
    
    }
    
    warn;
    
    {
      my $file = "$tmp_dir/foo.txt";
      my $stream = Sys::IO->fopen($file, "w");
      
      unless (Sys->f($file)) {
        return 0;
      }
      
      my $fd = Sys->fileno($stream);
      
      unless ($fd >= 0) {
        return 0;
      }
    }
    
    warn;
    
    return 1;
  }
  
  static method fopen : int () {
    
    my $test_tmp_dir = &TEST_TMP_DIR;
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_empty.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        return 0;
      }
    }
    
    {
      my $file = "$test_dir_ftest/not_found.txt";
      eval { Sys::IO->fopen($file, "rb"); };
      
      unless ($@) {
        return 0;
      }
      
      unless (Fn->contains($@, "not_found.txt")) {
        return 0;
      }
      
      unless (eval_error_id == basic_type_id Error::System) {
        return 0;
      }
    }
    
    {
      my $file = "$test_dir_ftest/file_empty.txt";
      my $stream_ref = [(Sys::IO::FileStream)undef];
      Sys->open($stream_ref, "<", $file);
      
      unless ($stream_ref->[0]) {
        return 0;
      }
    }
    
    {
      my $file = "$test_tmp_dir/あいうえお.txt";
      my $stream_ref = [(Sys::IO::FileStream)undef];
      
      Sys->open($stream_ref, ">", $file);
      
      unless ($stream_ref->[0]) {
        return 0;
      }
      
    }
    
    return 1;
  }
  
  static method fdopen : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_empty.txt";
      my $fd = Sys::IO->open($file, IO->O_RDWR, 0666);
      
      unless ($fd >= 0) {
        return 0;
      }
      
      my $stream = Sys::IO->fdopen($fd, "rb");
      
      unless ($stream) {
        return 0;
      }
    }
    
    {
      eval { Sys::IO->fdopen(-1, "rb"); };
      
      unless ($@) {
        return 0;
      }
    }
    
    {
      my $file = "$test_dir_ftest/file_empty.txt";
      my $fd = Sys::IO->open($file, IO->O_RDWR, 0666);
      
      unless ($fd >= 0) {
        return 0;
      }
      
      my $stream_ref = [(Sys::IO::FileStream)undef];
      Sys->fdopen($stream_ref, "<", $fd);
      
      unless ($stream_ref->[0]) {
        return 0;
      }
    }
    
    
    
    return 1;
  }

  static method fread : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        return 0;
      }
      
      my $buffer = (mutable string)new_string_len 4;
      my $size = 1;
      my $length = 4;
      
      my $read_length = 0;
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      
      unless ($buffer eq "abcd") {
        return 0;
      }
     
      unless ($read_length == 4) {
        return 0;
      }
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      
      unless ($buffer eq "efgh") {
        return 0;
      }
      
      unless ($read_length == 4) {
        return 0;
      }
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      unless ($read_length == 0) {
        return 0;
      }
    }
    
    # Big buffer size
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        return 0;
      }
      
      my $buffer = (mutable string)new_string_len 4096;
      my $size = 1;
      my $length = 4;
      
      my $read_length = 0;
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      
      unless (Fn->substr($buffer, 0, 4) eq "abcd") {
        return 0;
      }
     
      unless ($read_length == 4) {
        return 0;
      }
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      
      unless (Fn->substr($buffer, 0, 4) eq "efgh") {
        return 0;
      }
      
      unless ($read_length == 4) {
        return 0;
      }
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      unless ($read_length == 0) {
        return 0;
      }
    }
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        return 0;
      }
      
      my $buffer = (mutable string)new_string_len 4;
      my $size = 1;
      my $length = 4;
      
      my $read_length = 0;
      
      $read_length = Sys->read($stream, $buffer, $length, 0);
      
      unless ($buffer eq "abcd") {
        return 0;
      }
     
      unless ($read_length == 4) {
        return 0;
      }
      
      $read_length = Sys->read($stream, $buffer, $length);
      
      unless ($buffer eq "efgh") {
        return 0;
      }
      
      unless ($read_length == 4) {
        return 0;
      }
      
      $read_length = Sys->read($stream, $buffer, $length);
      unless ($read_length == 0) {
        return 0;
      }
    }
    
    return 1;
  }

  static method feof : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        return 0;
      }
      
      my $buffer = (mutable string)new_string_len 4;
      my $size = 1;
      my $length = 4;
      
      my $read_length = 0;
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      
      unless ($buffer eq "abcd") {
        return 0;
      }
     
      unless ($read_length == 4) {
        return 0;
      }
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      
      unless ($buffer eq "efgh") {
        return 0;
      }
      
      unless ($read_length == 4) {
        return 0;
      }
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      unless ($read_length == 0) {
        return 0;
      }
      
      my $feof = Sys::IO->feof($stream);
      
      unless ($feof) {
        return 0;
      }
    }
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        return 0;
      }
      
      my $buffer = (mutable string)new_string_len 4;
      my $size = 1;
      my $length = 4;
      
      my $read_length = 0;
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      
      unless ($buffer eq "abcd") {
        return 0;
      }
     
      unless ($read_length == 4) {
        return 0;
      }
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      
      unless ($buffer eq "efgh") {
        return 0;
      }
      
      unless ($read_length == 4) {
        return 0;
      }
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      unless ($read_length == 0) {
        return 0;
      }
      
      my $feof = Sys->eof($stream);
      
      unless ($feof) {
        return 0;
      }
    }
    
    return 1;
  }

  static method ferror : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        return 0;
      }
      
      my $buffer = (mutable string)new_string_len 4;
      my $size = 1;
      my $length = 4;
      
      my $read_length = 0;
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      
      unless ($buffer eq "abcd") {
        return 0;
      }
     
      unless ($read_length == 4) {
        return 0;
      }
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      
      unless ($buffer eq "efgh") {
        return 0;
      }
      
      unless ($read_length == 4) {
        return 0;
      }
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      unless ($read_length == 0) {
        return 0;
      }
      
      my $ferror = Sys::IO->ferror($stream);
      
      if ($ferror) {
        return 0;
      }
    }
    
    return 1;
  }

  static method clearerr : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        return 0;
      }
      
      my $buffer = (mutable string)new_string_len 4;
      my $size = 1;
      my $length = 4;
      
      my $read_length = 0;
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      
      unless ($buffer eq "abcd") {
        return 0;
      }
     
      unless ($read_length == 4) {
        return 0;
      }
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      
      unless ($buffer eq "efgh") {
        return 0;
      }
      
      unless ($read_length == 4) {
        return 0;
      }
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      unless ($read_length == 0) {
        return 0;
      }
      
      Sys::IO->clearerr($stream);
    }
    
    return 1;
  }

  static method getc : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        return 0;
      }
      
      my $char = 0;
      
      $char = Sys::IO->getc($stream);
      unless ($char == 'a') {
        return 0;
      }
      $char = Sys::IO->getc( $stream);
      unless ($char == 'b') {
        return 0;
      }
      $char = Sys::IO->getc( $stream);
      unless ($char == 'c') {
        return 0;
      }
      $char = Sys::IO->getc( $stream);
      unless ($char == 'd') {
        return 0;
      }
      $char = Sys::IO->getc( $stream);
      unless ($char == 'e') {
        return 0;
      }
      $char = Sys::IO->getc( $stream);
      unless ($char == 'f') {
        return 0;
      }
      $char = Sys::IO->getc( $stream);
      unless ($char == 'g') {
        return 0;
      }
      $char = Sys::IO->getc( $stream);
      unless ($char == 'h') {
        return 0;
      }
      $char = Sys::IO->getc( $stream);
      unless ($char == IO->EOF) {
        return 0;
      }
    }
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        return 0;
      }
      
      my $char = 0;
      
      $char = Sys->getc($stream);
      unless ($char == 'a') {
        return 0;
      }
      $char = Sys->getc( $stream);
      unless ($char == 'b') {
        return 0;
      }
      $char = Sys->getc( $stream);
      unless ($char == 'c') {
        return 0;
      }
      $char = Sys->getc( $stream);
      unless ($char == 'd') {
        return 0;
      }
      $char = Sys->getc( $stream);
      unless ($char == 'e') {
        return 0;
      }
      $char = Sys->getc( $stream);
      unless ($char == 'f') {
        return 0;
      }
      $char = Sys->getc( $stream);
      unless ($char == 'g') {
        return 0;
      }
      $char = Sys->getc( $stream);
      unless ($char == 'h') {
        return 0;
      }
      $char = Sys->getc( $stream);
      unless ($char == IO->EOF) {
        return 0;
      }
    }
    
    {
      my $file = "$test_dir_ftest/newline_lf_only.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        warn dump $stream;
        return 0;
      }
      
      my $char = 0;
      
      $char = Sys::IO->getc($stream);
      unless ($char == '\n') {
        warn $char;
        return 0;
      }
      $char = Sys::IO->getc( $stream);
      unless ($char == IO->EOF) {
        warn $char;
        return 0;
      }
    }
    
    return 1;
  }

  static method fgets : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_new_lines.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        warn $stream;
        return 0;
      }
      
      my $buffer = (mutable string)new_string_len 4;
      my $buffer_zero = copy $buffer;
      my $size = length $buffer;
      
      Sys::IO->fgets($buffer, $size, $stream);
      
      unless ($buffer eq "a\n\0\0") {
        warn dump $buffer;
        return 0;
      }
      
      Fn->memcpy($buffer, 0, $buffer_zero, 0, $size);
      Sys::IO->fgets($buffer, $size, $stream);
      
      unless ($buffer eq "xxx\0") {
        warn dump $buffer;
        return 0;
      }
      
      Fn->memcpy($buffer, 0, $buffer_zero, 0, $size);
      Sys::IO->fgets($buffer, $size, $stream);
      
      unless ($buffer->[0] == '\n') {
        warn dump $buffer;
        return 0;
      }
      unless ($buffer eq "\n\0\0\0") {
        warn dump $buffer;
        return 0;
      }
      
      Fn->memcpy($buffer, 0, $buffer_zero, 0, $size);
      Sys::IO->fgets($buffer, $size, $stream);
      
      unless ($buffer eq "bc\n\0") {
        warn dump $buffer;
        return 0;
      }
      
      Fn->memcpy($buffer, 0, $buffer_zero, 0, $size);
      Sys::IO->fgets($buffer, $size, $stream);
      
      unless ($buffer eq "d\0\0\0") {
        warn dump $buffer;
        return 0;
      }
      
      Fn->memcpy($buffer, 0, $buffer_zero, 0, $size);
      Sys::IO->fgets($buffer, $size, $stream);
    }
    
    return 1;
  }
  
  static method fwrite : int ($tmp_dir : string) {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      {
        my $file = "$tmp_dir/foo.txt";
        my $stream = Sys::IO->fopen($file, "wb");
        
        unless ($stream) {
          return 0;
        }
        
        my $write_length = 0;
        my $size = 1;
        my $length = 4;
        
        $write_length = Sys::IO->fwrite("abcd", $size, $length, $stream);
        unless ($write_length == 4) {
          return 0;
        }
        
        $write_length = Sys::IO->fwrite("efgh", $size, $length, $stream);
        unless ($write_length == 4) {
          return 0;
        }
        
        Sys::IO->fclose($stream);
      }
      
      {
        my $file = "$tmp_dir/foo.txt";
        my $stream = Sys::IO->fopen($file, "rb");
        
        unless ($stream) {
          return 0;
        }
        
        my $buffer = (mutable string)new_string_len 4;
        my $size = 1;
        my $length = 4;
        
        my $read_length = 0;
        
        $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
        
        unless ($buffer eq "abcd") {
          return 0;
        }
        
        unless ($read_length == 4) {
          return 0;
        }

        $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
        
        unless ($buffer eq "efgh") {
          return 0;
        }
        
        unless ($read_length == 4) {
          return 0;
        }
        
        $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
        
        unless ($read_length == 0) {
          return 0;
        }
        
        Sys::IO->fclose($stream);
      }
      
      {
        my $file = "$tmp_dir/foo.txt";
        my $stream = Sys::IO->fopen($file, "wb");
        
        unless ($stream) {
          return 0;
        }
        
        my $size = 1;
        my $length = 4;
        
        Sys->print($stream, "abcd");
        
        Sys->print($stream, "efgh");
        
        Sys::IO->fclose($stream);
      }
      
      {
        my $file = "$tmp_dir/foo.txt";
        my $stream = Sys::IO->fopen($file, "wb");
        
        unless ($stream) {
          return 0;
        }
        
        my $size = 1;
        my $length = 4;
        
        Sys->say($stream, "abcd");
        
        Sys->say($stream, "efgh");
        
        Sys::IO->fclose($stream);
      }
      
      {
        my $file = "$tmp_dir/foo.txt";
        my $stream = Sys::IO->fopen($file, "wb");
        
        unless ($stream) {
          return 0;
        }
        
        my $size = 1;
        my $length = 4;
        
        Sys->say($stream, "abcd");
        
        Sys->say($stream, "efgh");
        
        Sys::IO->fclose($stream);
      }
      
      {
        my $file = "$tmp_dir/foo.txt";
        my $stream = Sys::IO->fopen($file, "wb");
        
        unless ($stream) {
          return 0;
        }
        
        my $size = 1;
        my $length = 4;
        
        Sys->printf($stream, "abc%s", ["d"]);
        
        Sys->printf($stream, "efg%s", ["h"]);
        
        Sys::IO->fclose($stream);
      }
    }
    
    # Big buffer
    {
      {
        my $file = "$tmp_dir/foo.txt";
        my $stream = Sys::IO->fopen($file, "wb");
        
        unless ($stream) {
          return 0;
        }
        
        my $buffer = new_string_len 4096;

        my $write_length = 0;
        my $size = 1;
        my $length = 4;
        
        Fn->memcpy($buffer, 0, "abcd", 0, $length);
        $write_length = Sys::IO->fwrite("abcd", $size, $length, $stream);
        unless ($write_length == $length) {
          return 0;
        }
        
        Fn->memcpy($buffer, 0, "efgh", 0, $length);
        $write_length = Sys::IO->fwrite("efgh", $size, $length, $stream);
        unless ($write_length == $length) {
          return 0;
        }
        
        Sys::IO->fclose($stream);
      }
      
      {
        my $file = "$tmp_dir/foo.txt";
        my $stream = Sys::IO->fopen($file, "rb");
        
        unless ($stream) {
          return 0;
        }

        my $buffer = (mutable string)new_string_len 4;
        my $size = 1;
        my $length = 4;
        
        my $read_length = 0;
        
        $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
        
        unless ($buffer eq "abcd") {
          return 0;
        }
        
        unless ($read_length == 4) {
          return 0;
        }

        $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
        
        unless ($buffer eq "efgh") {
          return 0;
        }
        
        unless ($read_length == 4) {
          return 0;
        }

        $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
        
        unless ($read_length == 0) {
          return 0;
        }
        
        Sys::IO->fclose($stream);
      }
    }
    return 1;
  }

  static method fseek : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        return 0;
      }
      
      my $buffer = (mutable string)new_string_len 4;
      my $size = 1;
      my $length = 4;
      
      my $read_length = 0;
      
      my $streameek_status = Sys::IO->fseek($stream, 4, IO->SEEK_SET);
      
      unless ($streameek_status == 0) {
        return 0;
      }
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      
      unless ($buffer eq "efgh") {
        return 0;
      }
      
      unless ($read_length == 4) {
        return 0;
      }
    }
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        return 0;
      }
      
      my $buffer = (mutable string)new_string_len 4;
      my $size = 1;
      my $length = 4;
      
      my $read_length = 0;
      
      Sys->seek($stream, 4, IO->SEEK_SET);
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      
      unless ($buffer eq "efgh") {
        return 0;
      }
      
      unless ($read_length == 4) {
        return 0;
      }
    }
    return 1;
  }

  static method ftell : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        return 0;
      }
      
      my $buffer = (mutable string)new_string_len 4;
      my $size = 1;
      my $length = 4;
      
      my $read_length = 0;
      
      my $streameek_status = Sys::IO->fseek($stream, 4, IO->SEEK_SET);
      
      unless ($streameek_status == 0) {
        return 0;
      }
      
      my $offset = Sys::IO->ftell($stream);
      
      unless ($offset == 4) {
        return 0;
      }
    }
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        return 0;
      }
      
      my $buffer = (mutable string)new_string_len 4;
      my $size = 1;
      my $length = 4;
      
      my $read_length = 0;
      
      my $streameek_status = Sys::IO->fseek($stream, 4, IO->SEEK_SET);
      
      unless ($streameek_status == 0) {
        return 0;
      }
      
      my $offset = Sys->tell($stream);
      
      unless ($offset == 4) {
        return 0;
      }
    }
    return 1;
  }

  static method fflush : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_empty.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        return 0;
      }
      
      my $fflush_status = Sys::IO->fflush($stream);

      unless ($fflush_status == 0) {
        return 0;
      }
      
      my $fclose_status = Sys::IO->fclose($stream);
      
      unless ($fclose_status == 0) {
        return 0;
      }
    }
    
    
    
    return 1;
  }

  static method fclose : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_empty.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        return 0;
      }
      
      my $status = Sys::IO->fclose($stream);
      
      unless ($status == 0) {
        return 0;
      }
    }
    
    
    
    return 1;
  }

  static method flock : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_empty.txt";
      my $fd = Sys::IO->open($file, IO->O_RDONLY, IO->O_TRUNC);
      
      my $status_lock = Sys::IO->flock($fd, IO->LOCK_SH);
      
      unless ($status_lock == 0) {
        return 0;
      }

      my $status_unlock = Sys::IO->flock($fd, IO->LOCK_UN);
      
      unless ($status_unlock == 0) {
        return 0;
      }
      
      my $close_status = Sys::IO->close($fd);
      
      unless ($close_status == 0) {
        return 0;
      }
    }
    
    # The constant values for the flock function
    {
      IO->LOCK_SH;
      IO->LOCK_EX;
      IO->LOCK_UN;
    }
    
    {
      my $file = "$test_dir_ftest/file_empty.txt";
      my $fd = Sys::IO->open($file, IO->O_RDONLY, IO->O_TRUNC);
      
      my $status_lock = Sys::IO->flock($fd, IO->LOCK_SH);
      
      unless ($status_lock == 0) {
        return 0;
      }

      Sys->flock($fd, IO->LOCK_UN);
      
      my $close_status = Sys::IO->close($fd);
      
      unless ($close_status == 0) {
        return 0;
      }
    }
    
    return 1;
  }


  static method mkdir : int ($tmp_dir : string) {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    my $dir = "$tmp_dir/foo";
    
    my $status = Sys::IO->mkdir($dir, 0755);
    
    unless ($status == 0) {
      return 0;
    }
    
    unless (Sys->d($dir)) {
      return 0;
    }
    
    {
      eval { Sys::IO->mkdir($dir, 0755); };
      
      unless (Fn->contains($@, "foo")) {
        return 0;
      }
    }
    
    return 1;
  }

  static method umask : int ($tmp_dir : string) {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    my $dir = "$tmp_dir/foo";
    
    my $old_mask = Sys::IO->umask(IO->S_IRUSR);
    
    my $cur_mask = Sys::IO->umask(IO->S_IWUSR);

    unless ($cur_mask == IO->S_IRUSR) {
      return 0;
    }
    
    # Restore
    Sys::IO->umask($old_mask);
    
    # The constant values for permissions
    {
      IO->S_IRUSR;
      IO->S_IWUSR;
      IO->S_IRGRP;
      IO->S_IWGRP;
      IO->S_IROTH;
      IO->S_IWOTH;
    }
    
    return 1;
  }

  static method rmdir : int ($tmp_dir : string) {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    my $dir = "$tmp_dir/foo";
    
    Sys::IO->mkdir($dir, 0755);
    
    unless (Sys->d($dir)) {
      return 0;
    }
    
    my $status = Sys::IO->rmdir($dir);

    unless ($status == 0) {
      return 0;
    }
    
    if (Sys->e($dir)) {
      return 0;
    }
    
    {
      eval { Sys::IO->rmdir($dir); };
      unless (Fn->contains($@, "foo")) {
        return 0;
      }
    }
    
    return 1;
  }

  static method unlink : int ($tmp_dir : string) {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    
    my $file = "$tmp_dir/foo.txt";
    
    {
      Sys::IO->fopen($file, "w");
    }
    
    unless (Sys->f($file)) {
      return 0;
    }
    
    my $status = Sys::IO->unlink($file);
    
    unless ($status == 0) {
      return 0;
    }
    
    if (Sys->e($file)) {
      return 0;
    }
    
    {
      eval { Sys::IO->unlink($file); };
      unless (Fn->contains($@, "foo.txt")) {
        return 0;
      }
    }
    
    return 1;
  }

  static method rename : int ($tmp_dir : string) {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    my $file = "$tmp_dir/foo.txt";
    
    {
      Sys::IO->fopen($file, "w");
    }
    
    unless (Sys->e($file)) {
      return 0;
    }
    
    my $new_file = "$tmp_dir/foo_new.txt";
    my $status = Sys::IO->rename($file, $new_file);
    
    unless ($status == 0) {
      return 0;
    }
    
    if (Sys->e($file)) {
      return 0;
    }

    unless (Sys->e($new_file)) {
      return 0;
    }
    
    {
      eval { Sys::IO->rename($file, $new_file); };
      unless (Fn->contains($@, "foo.txt")) {
        return 0;
      }
      unless (Fn->contains($@, "foo_new.txt")) {
        return 0;
      }
    }
    
    return 1;
  }

  static method getcwd : int () {
    
    {
      my $ret_buf = Sys::IO->getcwd(undef, 0);
      
      unless ($ret_buf) {
        return 0;
      }
      
      warn "[Test Output]getcwd:$ret_buf";
    }
    
    {
      my $dir = "$TEST_TMP_DIR/getcwd_あ";
      
      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);
      
      my $cwd = Sys::IO->getcwd(undef, 0);
      
      warn "[Test Output]getcwd non-ascii:$cwd";
    }
    
    return 1;
  }
  
  static method _getdcwd : int () {
    
    if (Sys::OS->is_windows) {
      my $ret_buf = Sys::IO->_getdcwd(0, undef, 1);
      
      unless ($ret_buf) {
        return 0;
      }
      
      warn "[Test Output]_getdcwd:$ret_buf";
      
      {
        my $dir = "$TEST_TMP_DIR/getdcwd_あ";
        
        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);
        
        my $dcwd = Sys::IO->_getdcwd(0, undef, 1);
        
        warn "[Test Output]_getdcwd non-ascii:$dcwd";
      }
    }
    else {
      warn "[Test Skip]_getdcwd is not supported in this system.";
    }
    
    return 1;
  }
  
  static method realpath : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    my $file = "$test_dir_ftest/dir_empty/../file_empty.txt";
    
    {
      my $ret_resolved_path = Sys::IO->realpath($file, undef);
      
      unless ($ret_resolved_path) {
        return 0;
      }
      
      Fn->shorten_null_char($ret_resolved_path);
      
      warn "[Test Output]realpath(undef):Expected:$test_dir_ftest/file_empty.txt,Got:$ret_resolved_path";
      
      unless ($ret_resolved_path eq "$test_dir_ftest/file_empty.txt") {
        return 0;
      }
    }
    
    {
      my $resolved_path = (mutable string)new_string_len 256;
      my $ret_resolved_path = Sys::IO->realpath($file, $resolved_path);
      
      unless ($ret_resolved_path) {
        return 0;
      }
      
      Fn->shorten_null_char($ret_resolved_path);
      
      warn "[Test Output]realpath:Expected:$test_dir_ftest/file_empty.txt,Got:$ret_resolved_path";
      
      unless ($ret_resolved_path eq "$test_dir_ftest/file_empty.txt") {
        return 0;
      }
    }
    
    {
      eval { Sys::IO->realpath("$file/not_found.txt", undef); };
      unless (Fn->contains($@, "not_found.txt")) {
        return 0;
      }
    }

    return 1;
  }
  
  private static method replace_chars : void ($string : mutable string, $from : byte, $to : byte) {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    unless ($string) {
      die "\$string must be defined.";
    }
    
    my $string_length = length $string;
    for (my $i = 0; $i < $string_length; $i++) {
      if ($string->[$i] == $from) {
        $string->[$i] = $to;
      }
    }
  }
  
  static method chdir : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    my $dir = "$test_dir_ftest/dir_empty";
    
    my $status = Sys::IO->chdir($dir);
    
    unless ($status == 0) {
      return 0;
    }
    
    my $cwd = Sys::IO->getcwd(undef, 0);
    unless (Fn->contains($cwd, "dir_empty")) {
      return 0;
    }
    
    {
      eval { Sys::IO->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);
      
      my $cwd = Sys::IO->getcwd(undef, 0);
      
      warn "[Test Output]chdir non-ascii:$cwd";
    }
    
    warn "[Test Output]getcwd cwd_save:" . Sys::IO->getcwd(undef, 0);
    
    return 1;
  }

  static method chmod : int ($tmp_dir : string) {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    my $file = "$tmp_dir/foo.txt";
    my $stream = Sys::IO->fopen($file, "w");
    
    unless (Sys->f($file)) {
      return 0;
    }
    
    Sys::IO->fclose($stream);
    
    my $status = Sys::IO->chmod($file, 0755);
    
    unless ($status == 0) {
      return 0;
    }
    
    {
      eval { Sys::IO->chmod("$file/not_found.txt", 0755); };
      unless (Fn->contains($@, "not_found.txt")) {
        return 0;
      }
    }
    
    return 1;
  }

  static method chown : int ($tmp_dir : string) {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$tmp_dir/foo.txt";
      my $stream = Sys::IO->fopen($file, "w");
      
      unless (Sys->f($file)) {
        return 0;
      }
      
      Sys::IO->fclose($stream);
      
      my $status = Sys::IO->chown($file, -1, -1);
      
      unless ($status == 0) {
        return 0;
      }
      
      {
        eval { Sys::IO->chown("$file/not_found.txt", -1, -1); };
        unless (Fn->contains($@, "not_found.txt")) {
          return 0;
        }
      }
    }
    
    {
      my $file = "$tmp_dir/foo.txt";
      my $stream = Sys::IO->fopen($file, "w");
      
      unless (Sys->f($file)) {
        return 0;
      }
      
      Sys::IO->fclose($stream);
      
      Sys->chown(-1, -1, $file);
      
      {
        eval { Sys->chown(-1, -1, "$file/not_found.txt"); };
        unless (Fn->contains($@, "not_found.txt")) {
          return 0;
        }
      }
    }
    return 1;
  }

  static method symlink : int ($tmp_dir : string) {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    my $file = "$tmp_dir/foo.txt";
    {
      my $stream = Sys::IO->fopen($file, "wb");
      
      unless ($stream) {
        return 0;
      }
      Sys::IO->fclose($stream);
    }
    
    my $file_symlink = "$tmp_dir/foo_link";
    {
      my $status = Sys::IO->symlink($file, $file_symlink);
      
      unless ($status == 0) {
        return 0;
      }
      
      my $exists_symlink_file = Sys->l($file_symlink);
      unless ($exists_symlink_file) {
        return 0;
      }
    }

    {
      eval { Sys::IO->symlink("$file/not_found.txt", "$file_symlink/not_found_symlink.txt"); };
      unless (Fn->contains($@, "not_found.txt")) {
        return 0;
      }
      unless (Fn->contains($@, "not_found_symlink.txt")) {
        return 0;
      }
    }
    
    return 1;
  }

  static method readlink : int ($tmp_dir : string) {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    my $file = "$tmp_dir/foo.txt";
    {
      my $stream = Sys::IO->fopen($file, "wb");
      
      unless ($stream) {
        return 0;
      }
      Sys::IO->fclose($stream);
    }
    
    my $file_symlink = "$tmp_dir/foo_link";
    {
      my $status = Sys::IO->symlink($file, $file_symlink);
      
      unless ($status == 0) {
        return 0;
      }
      
      my $exists_symlink_file = Sys->l($file_symlink);
      unless ($exists_symlink_file) {
        return 0;
      }
    }
    
    {
      my $buffer = (mutable string)new_string_len 255;
      my $replaced_length = Sys::IO->readlink($file_symlink, $buffer, length $buffer);
      
      unless ($replaced_length == length $file) {
        return 0;
      }
      
      Fn->shorten_null_char($buffer);
      
      unless ($buffer eq $file) {
        return 0;
      }
    }
    
    {
      my $buffer = (mutable string)new_string_len 255;
      eval {Sys::IO->readlink("$file_symlink/not_found.txt", $buffer, length $buffer); };
      unless (Fn->contains($@, "not_found.txt")) {
        return 0;
      }
    }

    return 1;
  }
  
  static method readline : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    # Basic
    {
      my $file = "$test_dir_ftest/readline_basic.txt";
      
      my $stream = Sys::IO->fopen($file, "rb");
      {
        my $line = Sys->readline($stream);
        
        unless ($line eq "abcd\n") {
          warn dump $line;
          return 0;
        }
      }
      
      {
        my $line = Sys->readline($stream);
        
        unless ($line eq "fghi\n") {
          warn dump $line;
          return 0;
        }
      }
      
      {
        my $line = Sys->readline($stream);
        
        unless ($line eq "klm\n") {
          warn dump $line;
          return 0;
        }
      }
      
      {
        my $line = Sys->readline($stream);
        
        unless ($line == undef) {
          warn dump $line;
          return 0;
        }
      }
    }
    
    # With while
    {
      my $file = "$test_dir_ftest/readline_basic.txt";
      
      my $stream = Sys::IO->fopen($file, "rb");
      
      my $lstrings = StringList->new((string[])undef);
      while (my $line = Sys->readline($stream)) {
        $lstrings->push($line);
      }
      
      my $strings = $lstrings->to_array;
      
      unless (Array->equals_string($strings, ["abcd\n", "fghi\n", "klm\n"])) {
        warn dump $strings;
        return 0;
      }
      
    }
    
    # EOF
    {
      my $file = "$test_dir_ftest/readline_eof.txt";
      
      my $stream = Sys::IO->fopen($file, "rb");
      
      {
        my $line = Sys->readline($stream);
        
        unless ($line eq "abcd\n") {
          warn dump $line;
          return 0;
        }
      }
      
      {
        my $line = Sys->readline($stream);
        
        unless ($line eq "fghi\n") {
          warn dump $line;
          return 0;
        }
      }
      
      {
        my $line = Sys->readline($stream);
        
        warn dump $line;
        
        unless ($line eq "\n") {
          warn dump $line;
          return 0;
        }
      }
      
      {
        my $line = Sys->readline($stream);
        
        warn dump $line;
        
        unless ($line eq "klm") {
          warn dump $line;
          return 0;
        }
      }
      
      {
        my $line = Sys->readline($stream);
        
        unless ($line == undef) {
          warn dump $line;
          return 0;
        }
      }
      
    }
    
    # Long lines
    {
      my $file = "$test_dir_ftest/readline_long_lines.txt";
      
      my $stream = Sys::IO->fopen($file, "rb");
      
      {
        my $line = Sys->readline($stream);
        
        unless ($line eq "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n") {
          warn dump $line;
          return 0;
        }
      }
      
      {
        my $line = Sys->readline($stream);
        
        unless ($line eq "fghi\n") {
          warn dump $line;
          return 0;
        }
      }
      
      {
        my $line = Sys->readline($stream);
        
        unless ($line eq "klm\n") {
          warn dump $line;
          return 0;
        }
      }
      
      {
        my $line = Sys->readline($stream);
        
        unless ($line == undef) {
          warn dump $line;
          return 0;
        }
      }
      
    }
    
    # With chomp
    {
      my $file = "$test_dir_ftest/readline_basic.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      {
        my $line = Sys->readline($stream);
        Fn->chomp($line);
        unless ($line eq "abcd") {
          warn dump $line;
          return 0;
        }
      }
    }
    
    {
      my $file = "$test_dir_ftest/readline_basic.txt";
      
      my $stream = Sys::IO->fopen($file, "rb");
      
      {
        my $line = Sys->readline($stream);
        unless ($line eq "abcd\n") {
          warn dump $line;
          return 0;
        }
      }
      
      {
        my $line = Sys->readline($stream);
        unless ($line eq "fghi\n") {
          warn dump $line;
          return 0;
        }
      }
      
      {
        my $line = Sys->readline($stream);
        unless ($line eq "klm\n") {
          warn dump $line;
          return 0;
        }
      }
      
      {
        my $line = Sys->readline($stream);
        unless ($line == undef) {
          warn dump $line;
          return 0;
        }
      }
    }
    
    return 1;
  }
  
  static method truncate : int ($tmp_dir : string) {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    my $file = "$tmp_dir/foo.txt";
    {
      my $stream = Sys::IO->fopen($file, "wb");
      
      my $write_length = 0;
      my $size = 1;
      my $length = 4;
      
      $write_length = Sys::IO->fwrite("abcd", $size, $length, $stream);
      unless ($write_length == 4) {
        return 0;
      }
    }
    
    warn "[Test Output]" . Sys->s($file);
    unless (Sys->s($file) > 0) {
      return 0;
    }
    
    Sys::IO->truncate($file, 0);
    
    warn "[Test Output]" . Sys->s($file);
    unless (Sys->s($file) == 0) {
      return 0;
    }
    
    {
      eval { Sys::IO->truncate("$file/not_found.txt", 0); };
      unless (Fn->contains($@, "not_found.txt")) {
        return 0;
      }
    }
    
    {
      my $file = "$TEST_TMP_DIR/truncate_あ.txt";
      
      Sys->open(my $_ = [(Sys::IO::FileStream)undef], ">", $file);
      my $fh = $_->[0];
      
      Sys::IO->truncate($file, 0);
    }
    
    return 1;
  }

  static method ftruncate : int ($tmp_dir : string) {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$tmp_dir/foo.txt";
      {
        my $stream = Sys::IO->fopen($file, "wb");
        
        my $write_length = 0;
        my $size = 1;
        my $length = 4;
        
        $write_length = Sys::IO->fwrite("abcd", $size, $length, $stream);
        unless ($write_length == 4) {
          return 0;
        }
      }
      
      warn "[Test Output]" . Sys->s($file);
      unless (Sys->s($file) > 0) {
        return 0;
      }
        
      {
        my $stream = Sys::IO->fopen($file, "wb");
        my $status = Sys::IO->ftruncate(Sys::IO->fileno($stream), 0);
        unless ($status == 0) {
          return 0;
        }
      }
      
      warn "[Test Output]" . Sys->s($file);
      unless (Sys->s($file) == 0) {
        return 0;
      }
    }
    
    {
      my $file = "$tmp_dir/foo.txt";
      {
        my $stream = Sys::IO->fopen($file, "wb");
        
        my $write_length = 0;
        my $size = 1;
        my $length = 4;
        
        $write_length = Sys::IO->fwrite("abcd", $size, $length, $stream);
        unless ($write_length == 4) {
          return 0;
        }
      }
      
      unless (Sys->s($file) > 0) {
        return 0;
      }
        
      {
        my $stream = Sys::IO->fopen($file, "wb");
        Sys->truncate(Sys::IO->fileno($stream), 0);
      }
      
      unless (Sys->s($file) == 0) {
        return 0;
      }
    }
    return 1;
  }

  static method ungetc : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        return 0;
      }
      
      my $char = 0;
      
      $char = Sys::IO->getc($stream);
      unless ($char == 'a') {
        return 0;
      }
      
      Sys::IO->ungetc('z', $stream);
      
      $char = Sys::IO->getc($stream);
      
      unless ($char == 'z') {
        return 0;
      }
    }
    
    return 1;
  }

  static method fsync : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_empty.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        return 0;
      }
      
      my $fsync_status = Sys::IO->fsync(Sys::IO->fileno($stream));

      unless ($fsync_status == 0) {
        return 0;
      }
      
      my $fclose_status = Sys::IO->fclose($stream);
      
      unless ($fclose_status == 0) {
        return 0;
      }
    }
    
    
    
    return 1;
  }

  static method setvbuf : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      my $buf = (mutable string)new_string_len IO->BUFSIZ;
      my $mode = Sys::IO::Constant->_IOFBF;
      
      my $status = Sys::IO->setvbuf($stream, $buf, $mode, IO->BUFSIZ);
      unless ($status == 0) {
        return 0;
      }
    }

    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      my $mode = Sys::IO::Constant->_IOFBF;
      
      my $status = Sys::IO->setvbuf($stream, undef, $mode, IO->BUFSIZ);
      unless ($status == 0) {
        return 0;
      }
    }
    
    # Constant values
    {
      Sys::IO::Constant->_IONBF;
      Sys::IO::Constant->_IOLBF;
      Sys::IO::Constant->_IOFBF;
    }
    
    return 1;
  }

  static method setbuf : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      my $buf = (mutable string)new_string_len IO->BUFSIZ;
      my $mode = Sys::IO::Constant->_IOFBF;
      
      Sys::IO->setbuf($stream, $buf);
    }
    
    return 1;
  }

  static method setbuffer : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      my $buf = (mutable string)new_string_len IO->BUFSIZ;
      my $mode = Sys::IO::Constant->_IOFBF;
      
      Sys::IO->setbuffer($stream, $buf, IO->BUFSIZ);
    }
    
    return 1;
  }

  static method setlinebuf : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest/file_bytes8.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      my $buf = (mutable string)new_string_len IO->BUFSIZ;
      my $mode = Sys::IO::Constant->_IOFBF;
      
      Sys::IO->setlinebuf($stream);
    }
    
    return 1;
  }

  static method freopen : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file0 = "$test_dir_ftest/bar.txt";
      my $file = "$test_dir_ftest/foo.txt";
      my $stream0 = Sys::IO->fopen($file0, "wb");
      my $stream = Sys::IO->freopen($file, "wb", $stream0);
      
      unless ($stream) {
        return 0;
      }

      my $write_length = 0;
      my $size = 1;
      my $length = 4;
      
      $write_length = Sys::IO->fwrite("abcd", $size, $length, $stream);
      unless ($write_length == 4) {
        return 0;
      }
      
      Sys::IO->fclose($stream);
    }
    
    {
      my $file = "$test_dir_ftest/foo.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      unless ($stream) {
        return 0;
      }

      my $buffer = (mutable string)new_string_len 4;
      my $size = 1;
      my $length = 4;
      
      my $read_length = 0;
      
      $read_length = Sys::IO->fread($buffer, $size, $length, $stream);
      
      unless ($buffer eq "abcd") {
        return 0;
      }
      
      Sys::IO->fclose($stream);
    }
    
    return 1;
  }
  
  static method opendir : int () {
    
    my $test_dir = &TEST_DIR;
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $file = "$test_dir_ftest";
      
      my $stream = Sys::IO->opendir($test_dir);
      
      unless ($stream) {
        return 0;
      }
    }
    
    {
      my $file = "$test_dir_ftest";
      
      my $dh_ref = [(Sys::IO::DirStream)undef];
      
      Sys->opendir($dh_ref, $test_dir);
      
      unless ($dh_ref->[0]) {
        return 0;
      }
      
      Sys->closedir($dh_ref->[0]);
    }
    
    {
      my $dir = "$TEST_TMP_DIR/opendir_あ";
      
      Sys->mkdir($dir);
      
      my $ds = Sys::IO->opendir($dir);
      
      Sys->readdir($ds);
    }
    
    return 1;
  }
  
  static method readdir : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $dir = "$test_dir_ftest";
      
      my $stream = Sys::IO->opendir($dir);
      
      Fn->defer([$stream : Sys::IO::DirStream] method : void () {
        Sys::IO->closedir($stream);
      });
      
      unless ($stream) {
        return 0;
      }
      
      Sys::IO->rewinddir($stream);
      Sys->rewinddir($stream);
      
      {
        my $current_offset = Sys::IO->telldir($stream);
        unless ($current_offset == 0) {
          return 0;
        }
      }
      
      {
        my $current_offset = Sys->telldir($stream);
        unless ($current_offset == 0) {
          return 0;
        }
      }
      
      my $check_file_count = 0;
      while (my $dirent = Sys::IO->readdir($stream)) {
        my $d_name = $dirent->d_name;
        
        if ($d_name eq "foo.txt") {
          $check_file_count++;
        }
        elsif ($d_name eq "bar.txt") {
          $check_file_count++;
        }
      }
      
      unless ($check_file_count == 2) {
        return 0;
      }
    }
    
    {
      my $dir = "$test_dir_ftest";
      
      my $stream = Sys::IO->opendir($dir);
      
      Fn->defer([$stream : Sys::IO::DirStream] method : void () {
        Sys::IO->closedir($stream);
      });
      
      my $dirent = Sys::IO->readdir($stream);
      
      my $d_ino = $dirent->d_ino;
      
      warn "[Test Output]Sys::IO::Dirent:d_ino:$d_ino";
      
      if (Sys::OS->defined("__linux__")) {
        unless ($d_ino > 0) {
          return 0;
        }
      }
      
      # d_reclen
      my $d_reclen_not_supported = Sys::OS->defined("__CYGWIN__");
      if ($d_reclen_not_supported) {
        eval { $dirent->d_reclen; }
        unless ($@ && eval_error_id is_error Error::NotSupported) {
          return 0;
        }
      }
      else {
        my $d_reclen = $dirent->d_reclen;
        warn "[Test Output]Sys::IO::Dirent:d_reclen:$d_reclen";
        if (Sys::OS->defined("__linux__")) {
          unless ($d_reclen > 0) {
            return 0;
          }
        }
      }
      
      # d_type
      my $d_type_not_supported = Sys::OS->defined("_WIN32");
      if ($d_type_not_supported) {
        eval { $dirent->d_type; }
        unless ($@ && eval_error_id is_error Error::NotSupported) {
          return 0;
        }
      }
      else {
        my $d_type = $dirent->d_type;
        warn "[Test Output]Sys::IO::Dirent:d_type:$d_type";
        unless ($d_type > 0) {
          return 0;
        }
      }
      
      # d_off
      my $d_off_not_supported = Sys::OS->defined("_WIN32") || Sys::OS->defined("__CYGWIN__") || Sys::OS->defined("__APPLE__");
      if ($d_off_not_supported) {
        eval { $dirent->d_off; }
        unless ($@ && eval_error_id is_error Error::NotSupported) {
          return 0;
        }
      }
      else {
        my $d_off = $dirent->d_off;
        warn "[Test Output]Sys::IO::Dirent:d_off:$d_off";
        unless ($d_off > 0) {
          return 0;
        }
      }
    }
    
    return 1;
  }
  
  static method seekdir : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $dir_stream = Sys::IO->opendir($test_dir_ftest);
      
      my $original_offset = Sys::IO->telldir($dir_stream);
      
      unless ($original_offset == 0) {
        warn $original_offset;
        return 0;
      }
      
      my $dirent = Sys::IO->readdir($dir_stream);
      
      my $offset = Sys::IO->telldir($dir_stream);
      
      unless ($offset > 0) {
        warn $offset;
        return 0;
      }
      
      my $dirent_next = Sys::IO->readdir($dir_stream);
      
      my $dirent_next_d_name = $dirent_next->d_name;
      
      Sys::IO->seekdir($dir_stream, $offset);
      
      my $dirent2 = Sys::IO->readdir($dir_stream);
      
      my $dirent2_d_name = $dirent2->d_name;
      
      unless ($dirent) {
        warn;
        return 0;
      }
      
      unless ($dirent2) {
        warn;
        return 0;
      }
      
      unless ($dirent2_d_name eq $dirent_next_d_name) {
        warn $dirent2_d_name;
        warn $dirent_next_d_name;
        return 0;
      }
    }
    
    return 1;
  }
  
  static method telldir : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $dir_stream = Sys::IO->opendir($test_dir_ftest);
      
      my $original_offset = Sys::IO->telldir($dir_stream);
      
      unless ($original_offset == 0) {
        warn $original_offset;
        return 0;
      }
      
      my $dirent = Sys::IO->readdir($dir_stream);
      
      my $offset = Sys::IO->telldir($dir_stream);
      
      unless ($offset > 0) {
        warn $offset;
        return 0;
      }
      
      my $dirent_next = Sys::IO->readdir($dir_stream);
      
      my $dirent_next_d_name = $dirent_next->d_name;
      
      Sys::IO->seekdir($dir_stream, $offset);
      
      my $dirent2 = Sys::IO->readdir($dir_stream);
      
      my $dirent2_d_name = $dirent2->d_name;
      
      unless ($dirent) {
        warn;
        return 0;
      }
      
      unless ($dirent2) {
        warn;
        return 0;
      }
      
      unless ($dirent2_d_name eq $dirent_next_d_name) {
        warn $dirent2_d_name;
        warn $dirent_next_d_name;
        return 0;
      }
    }
    
    return 1;
  }
  
  static method rewinddir : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $dir_stream = Sys::IO->opendir($test_dir_ftest);
      
      my $dirent = Sys::IO->readdir($dir_stream);
      
      Sys::IO->rewinddir($dir_stream);
      
      my $dirent2 = Sys::IO->readdir($dir_stream);
      
      unless ($dirent) {
        warn;
        return 0;
      }
      
      unless ($dirent2) {
        warn;
        return 0;
      }
      
      unless ($dirent2->d_name eq $dirent->d_name) {
        warn;
        return 0;
      }
    }
    
    return 1;
  }
  
  static method closedir : int () {
    
    my $test_dir = &TEST_DIR;
    
    {
      my $dir_stream = Sys::IO->opendir($test_dir);
      
      unless ($dir_stream) {
        return 0;
      }
      
      if ($dir_stream->closed) {
        warn $dir_stream->closed;
        return 0;
      }
      
      Sys::IO->closedir($dir_stream);
      
      unless ($dir_stream->closed) {
        warn $dir_stream->closed;
        return 0;
      }
      
      # This test is needed for every OSs, but only Linux causes a system error.
      if (Sys->osname eq "linux") {
        eval { Sys::IO->readdir($dir_stream); }
        
        unless ($@ && eval_error_id isa_error Error::System) {
          warn "System call succeeded.";
          return 0;
        }
      }
    }
    
    
    
    return 1;
  }
  
  static method fcntl : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    if (Sys::OS->is_windows) {
      warn "[Test Skip]fcntl is not supported in this system";
    }
    else {
      my $dir = "$test_dir_ftest";
      
      {
        my $file = "$test_dir_ftest/file_empty.txt";
        my $fd = Sys::IO->open($file, IO->O_RDWR);
        
        unless ($fd >= 0) {
          return 0;
        }
        
        {
          my $ret = Sys::IO->fcntl($fd, IO->F_GETFL);
          
          unless ($ret >= 0) {
            return 0;
          }
          
          Sys::IO->fcntl($fd, IO->F_SETFL, $ret);
          
          my $ret2 = Sys::IO->fcntl($fd, IO->F_GETFL);
          
          unless ($ret == $ret2) {
            return 0;
          }
        }
        
        {
          my $current_flags = Sys::IO->fcntl($fd, IO->F_GETFL);
          my $ret = Sys::IO->fcntl($fd, IO->F_SETFL, $current_flags | IO->O_APPEND);
          
          unless ($ret == 0) {
            return 0;
          }
        }
        
        {
          my $ret = Sys->fcntl($fd, IO->F_GETFL);
          
          unless ($ret >= 0) {
            return 0;
          }
          
          my $ret2 = Sys->fcntl($fd, IO->F_GETFL);
          
          unless ($ret == $ret2) {
            return 0;
          }
        }
        
        {
          my $ret = Sys->fcntl($fd, IO->F_SETFL, IO->O_APPEND);
          
          unless ($ret == 0) {
            return 0;
          }
        }
        
        {
          my $flock = Sys::IO::Flock->new;
          $flock->set_l_type(IO->F_WRLCK);
          $flock->set_l_whence(IO->SEEK_SET);
          my $ret = Sys::IO->fcntl($fd, IO->F_SETLK, $flock);
          
          unless ($ret == 0) {
            return 0;
          }
        }
        
        Sys::IO->close($fd);
      }
      
    }
    
    return 1;
  }
  
  static method stdin : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $stdin = Sys::IO->stdin;
      
      unless (Sys->fileno($stdin) == IO->STDIN_FILENO) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method stdout : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $stdout = Sys::IO->stdout;
      
      unless (Sys->fileno($stdout) == IO->STDOUT_FILENO) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method stderr : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $stderr = Sys::IO->stderr;
      
      unless (Sys->fileno($stderr) == IO->STDERR_FILENO) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method spvm_stdin : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $spvm_stdin = Sys::IO->spvm_stdin;
      
      unless (Sys->fileno($spvm_stdin) > 2) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method spvm_stdout : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $spvm_stdout = Sys::IO->spvm_stdout;
      
      my $spvm_stdin = Sys::IO->spvm_stdin;
      
      unless (Sys->fileno($spvm_stdout) > Sys->fileno($spvm_stdin)) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method spvm_stderr : int () {
    
    my $test_dir_ftest = &TEST_DIR_FTEST;
    
    {
      my $spvm_stderr = Sys::IO->spvm_stderr;
      
      my $spvm_stdout = Sys::IO->spvm_stdout;
      
      unless (Sys->fileno($spvm_stderr) > Sys->fileno($spvm_stdout)) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method access : int () {
    
    my $test_tmp_dir = &TEST_TMP_DIR;
    
    {
      my $file = "$test_tmp_dir/access_あ.txt";
      
      Sys->open([(Sys::IO::FileStream)undef], ">", $file);
      
      my $ret = Sys::IO->access($file, 0);
      
      if ($ret) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method dup : int () {
    
    my $fd = Sys->fileno(Sys->STDERR);
    
    my $fd_clone = Sys::IO->dup($fd);
    
    Fn->defer([$fd_clone : int] method : void () {
      Sys::IO->close($fd_clone);
    });
    
    unless ($fd_clone > -1 && $fd_clone != $fd) {
      return 0;
    }
    
    return 1;
  }
  
  static method dup2 : int () {
    
    my $fd = Sys->fileno(Sys->STDERR);
    
    my $fd_clone = Sys::IO->dup($fd);
    
    Fn->defer([$fd_clone : int] method : void () {
      Sys::IO->close($fd_clone);
    });
    
    Sys::IO->dup2($fd, $fd_clone);
    
    return 1;
  }
  
}