class TestCase::Thread {
  use Thread;
  use Thread::ID;
  use Thread::ThisThread;
  
  our $RESULT : public cache int[];
  
  static method basic : int () {
    
    $TestCase::Thread::RESULT = new int[100];
    
    my $results = [0];
    my $thread = Thread->new([$results : int[]] method : void () {
    
      $results->[0] = 5;
      
      $TestCase::Thread::RESULT->[0] = 10;
    });
    
    $thread->join;
    
    unless ($TestCase::Thread::RESULT->[0] == 10) {
      return 0;
    }
    
    unless ($results->[0] == 5) {
      return 0;
    }
    
    return 1;
  }
  
  static method thread_id : int () {
    
    my $thread1 = Thread->new(method : void () {
    
    });
    
    my $thread2 = Thread->new(method : void () {
    
    });
    
    my $current_thread_id = Thread::ThisThread->get_id;
    
    unless (Thread::ID->eq($current_thread_id, $current_thread_id)) {
      return 0;
    }
    
    my $thread1_id = $thread1->get_id;
    
    my $thread2_id = $thread2->get_id;
    
    $thread1->join;
    
    $thread2->join;
    
    return 1;
  }
  
  static method exception : int () {
    
    # Create a thread that calls a method which throws an exception
    my $thread = Thread->new(method : void () {
      
      # Level 1 call
      TestCase::Thread->throw_exception_method;
    });
    
    # The exception in the thread should be converted to a warning,
    # and the program should continue without crashing.
    $thread->join;
    
    # If we reached here, the crash was avoided.
    return 1;
  }

  static method throw_exception_method : void () {
    # Level 2 call (origin of the exception)
    die "Exception in thread via method call";
  }
  
}