class TestCase::Copy {
  use Fn;
  use Complex_2d;
  use TestCase::Minimal;
  
  static method copy : int () {
    # undef
    {
      my $string = (string)undef;
      
      my $string_copy = copy $string;
      
      if ($string_copy) {
        return 0;
      }
    }
    
    # String
    {
      my $string = "abc";
      my $string_copy = copy $string;
      
      unless ($string_copy isa string) {
        return 0;
      }
      
      if ($string_copy == $string) {
        return 0;
      }
      
      unless ($string_copy eq "abc") {
        return 0;
      }
      
      if (is_read_only $string_copy) {
        return 0;
      }
      
      my $string_copy_mut = (mutable string)$string_copy;
      
      $string_copy_mut->[0] = 'd';
      
      unless ($string_copy_mut eq "dbc") {
        return 0;
      }
    }
    
    
    # Numeric array
    {
      # byte
      {
        my $nums = [(byte)1, 2, 3];
        my $nums_copy = copy $nums;
        
        unless ($nums_copy isa byte[]) {
          return 0;
        }
        
        if ($nums_copy == $nums) {
          return 0;
        }
        
        unless (Fn->equals_array_byte($nums_copy, $nums)) {
          return 0;
        }
      }
 
      # double
      {
        my $nums = [(double)1.1, 2.2, 3.3];
        my $nums_copy = copy $nums;
        
        unless ($nums_copy isa double[]) {
          return 0;
        }
        
        if ($nums_copy == $nums) {
          return 0;
        }
        
        unless (Fn->equals_array_double($nums_copy, $nums)) {
          return 0;
        }
      }
   }

    # Multi numeric  array
    {
      # Complex_2d;
      {
        my $nums = new Complex_2d[3];
        
        $nums->[0]{re} = 1;
        $nums->[0]{im} = 2;

        $nums->[2]{re} = 3;
        $nums->[2]{im} = 4;
        
        my $nums_copy = copy $nums;
        
        unless ($nums_copy isa Complex_2d[]) {
          return 0;
        }
        
        if ($nums_copy == $nums) {
          return 0;
        }
        
        unless (@$nums_copy == @$nums) {
          return 0;
        }
        
        unless ($nums_copy->[0]{re} == $nums->[0]{re}) {
          return 0;
        }
        unless ($nums_copy->[0]{im} == $nums->[0]{im}) {
          return 0;
        }
        unless ($nums_copy->[2]{re} == $nums->[2]{re}) {
          return 0;
        }
        unless ($nums_copy->[2]{im} == $nums->[2]{im}) {
          return 0;
        }
      }
    }

    
    # Exception
    {
      eval { copy TestCase::Minimal->new; };
      unless ($@) {
        return 0;
      }

      eval { copy new TestCase::Minimal[3]; };
      unless ($@) {
        return 0;
      }
    }
    
    $@ = undef;

    return 1;
  }
}