class TestCase::Sys::Signal {
  use Sys::Signal;
  use Sys::Signal::Constant as SIGNAL;
  use Sys::Process;
  use Sys;
  use Sys::Signal::Handler;
  
  static method kill : int () {
    
    {
      my $process_id = Sys->process_id;
      
      my $status = Sys::Signal->kill($process_id, 0);
      
      unless ($status == 0) {
        return 0;
      }
    }
    
    {
      my $process_id = Sys->process_id;
      
      Sys->kill(0, $process_id);
    }
    
    return 1;
  }
  
  static method raise : int () {
    
    my $status = Sys::Signal->raise(0);
    
    unless ($status == 0) {
      return 0;
    }
    
    return 1;
  }
  
  
  static method alarm : int () {
    
    # TODO
    {
      my $rest_time = Sys::Signal->alarm(1000);
      unless ($rest_time == 0) {
        return 0;
      }
    }
    
    {
      my $rest_time = Sys->alarm(1000);
      unless ($rest_time == 0) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method ualarm : int () {
    
    # TODO
    {
      my $rest_time = Sys::Signal->ualarm(100000, 0);
      unless ($rest_time == 0) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method signal : int () {
    
    {
      Sys::Signal->signal(SIGNAL->SIGTERM, Sys::Signal->SIG_DFL);
      
      my $old_signal_handler = Sys::Signal->signal(SIGNAL->SIGTERM, Sys::Signal->SIG_IGN);
      
      unless (Sys::Signal::Handler->eq($old_signal_handler, Sys::Signal->SIG_DFL)) {
        return 0;
      }
      
      if (Sys::Signal::Handler->eq($old_signal_handler, Sys::Signal->SIG_IGN)) {
        return 0;
      }
    }
    
    {
      Sys->signal(SIGNAL->SIGTERM, "DEFAULT");
      
      Sys->signal(SIGNAL->SIGTERM, "IGNORE");
    }
    
    return 1;
  }
  
  static method signal_go : int ($tmp_dir : string) {
    
    my $signal_output_file = "$tmp_dir/signal_output.txt";
    
    {
      Sys::Signal->signal(SIGNAL->SIGTERM, Sys::Signal->SIG_DFL);
      
      my $stream_ref = [(Sys::IO::FileStream)undef];
      Sys->open($stream_ref, ">", $signal_output_file);
      
      Fn->defer([$stream_ref : Sys::IO::FileStream[]] method : void () {
        Sys->close($stream_ref->[0]);
      });
      
      my $fd = Sys->fileno($stream_ref->[0]);
      
      Sys::Signal->SET_SIG_GO_WRITE_FD($fd);
      
      my $old_signal_handler = Sys::Signal->signal(SIGNAL->SIGTERM, Sys::Signal->SIG_GO);
      
      unless (Sys::Signal::Handler->eq($old_signal_handler, Sys::Signal->SIG_DFL)) {
        return 0;
      }
      
      $old_signal_handler = Sys::Signal->signal(SIGNAL->SIGTERM, Sys::Signal->SIG_GO);
      
      unless (Sys::Signal::Handler->eq($old_signal_handler, Sys::Signal->SIG_GO)) {
        return 0;
      }
      
      unless (Sys::OS->is_windows) {
        Sys->kill(SIGNAL->SIGTERM, Sys->process_id);
      }
    }
    
    unless (Sys::OS->is_windows) {
      my $stream_ref = [(Sys::IO::FileStream)undef];
      Sys->open($stream_ref, "<", $signal_output_file);
      
      Fn->defer([$stream_ref : Sys::IO::FileStream[]] method : void () {
        Sys->close($stream_ref->[0]);
      });
      
      my $buffer = (mutable string)new_string_len 4;
      Sys->read($stream_ref->[0], $buffer, 4);
      
      my $numbers = new int [1];
      
      Fn->memcpy($numbers, 0, $buffer, 0, 4);
      
      unless ($numbers->[0] == SIGNAL->SIGTERM) {
        return 0;
      }
    }
    
    return 1;
  }
}