class TestCase::Operator::String {
  use Fn;
  use Array;
  static method string_access : int () {
    
    # Read-only strings cannnot be converted to mutable strings
    {
      eval { (mutable string)"abc"; };
      unless ($@) {
        return 0;
      }
    }
    
    # String literal is read-only
    {
      my $string = "abc";
      unless (is_read_only $string) {
        return 0;
      }
    }
    
    # make_read_only
    {
      my $string = Fn->copy_string("abc");
      if (is_read_only $string) {
        return 0;
      }
      make_read_only $string;
      unless (is_read_only $string) {
        return 0;
      }
      
      eval { (mutable string)$string; };
      unless ($@) {
        return 0;
      }
    }
    
    # make_fixed_length
    {
      {
        my $string = Fn->copy_string("abc");
        if (is_fixed_length $string) {
          return 0;
        }
        make_fixed_length $string;
        unless (is_fixed_length $string) {
          return 0;
        }
      }
      
      {
        my $array = new int[3];
        if (is_fixed_length $array) {
          return 0;
        }
        make_fixed_length $array;
        unless (is_fixed_length $array) {
          return 0;
        }
      }
      
    }
    
    # Get the charactor
    {
      my $string = "abc";
      
      unless ($string->[0] == 'a') {
        return 0;
      }
      
      unless ($string->[1] == 'b') {
        return 0;
      }
      
      unless ($string->[2] == 'c') {
        return 0;
      }
    }
    
    # Set the character
    {
      my $string : mutable string = (mutable string)Fn->copy_string("abc");
      $string->[0] = 'd';
      $string->[1] = 'e';
      $string->[2] = 'f';
      
      unless ($string->[0] == 'd') {
        return 0;
      }
      
      unless ($string->[1] == 'e') {
        return 0;
      }
      
      unless ($string->[2] == 'f') {
        return 0;
      }
    }

    # Set the character - type inference
    {
      my $string = (mutable string)Fn->copy_string("abc");
      $string->[0] = 'd';
      $string->[1] = 'e';
      $string->[2] = 'f';
      
      unless ($string->[0] == 'd') {
        return 0;
      }
      
      unless ($string->[1] == 'e') {
        return 0;
      }
      
      unless ($string->[2] == 'f') {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method string_length : int () {
    # length Operator
    {
      my $string_length = length "abc";
      
      unless ($string_length == 3) {
        return 0;
      }
      
      return 1;
    }
    
    {
      my $string_length = length "";
      
      unless ($string_length == 0) {
        return 0;
      }
      
      return 1;
    }
    
    {
      my $string = (string)undef;
      my $string_length = length $string;
      
      unless ($string_length == 0) {
        return 0;
      }
      
      return 1;
    }
    
  }
  
  static method basic : int () {
    
    # Assign byte array to string
    {
      my $bytes = [(byte)'a', 'b', 'c'];
      my $string : string = (string)$bytes;
      
      unless ($string eq "abc") {
        return 0;
      }
      
      unless ($string != $bytes) {
        return 0;
      }
    }

    # Cast byte array to string
    {
      my $bytes = [(byte)'a', 'b', 'c'];
      my $string = (string)$bytes;
      
      unless ($string eq "abc") {
        return 0;
      }
      
      unless ($string != $bytes) {
        return 0;
      }
    }

    # Concat string
    {
      my $error = "First";
      (string)$error . "\n";
    }

    return 1;
  }

  static method new_string_len : int () {
    
    # Basic
    {
      my $message = new_string_len 3;
      
      unless ($message isa string) {
        return 0;
      }
      
      unless ($message eq "\0\0\0") {
        return 0;
      }
      
      my $message_mut = (mutable string)$message;
      
      $message_mut->[0] = 'a';
      $message_mut->[1] = 'b';
      $message_mut->[2] = 'c';
      
      unless ($message eq "abc") {
        return 0;
      }
    }
    
    # The length is 0
    {
      my $message = new_string_len(0);
      
      unless ($message eq "") {
        return 0;
      }
    }

    # The length is -1
    {
      eval { new_string_len -1; };
      unless ($@) {
        return 0;
      }
    }
    
    # Extra
    {
      # new_string_len
      {
        {
          my $string = new_string_len 3;
          
          unless ($string isa string) {
            return 0;
          }
          
          unless ($string is_compile_type mutable string) {
            return 0;
          }
        }
        
        {
          my $string = new_string_len 0;
          unless ($string) {
            return 0;
          }
          unless (length $string == 0) {
            return 0;
          }
        }
        
        {
          my $string = new_string_len 3;
          unless ($string) {
            return 0;
          }
          unless (length $string == 3) {
            return 0;
          }
        }
        
        {
          eval { new_string_len -1; };
          unless ($@) {
            return 0;
          }
        }
      }
    }
    
    return 1;
  }
}
