class TestCase::Module::Point3D {
  use Point3D;
  
  # Super class
  static method super_class : int () {
    
    {
      my $point3d = Point3D->new;
      unless ($point3d isa Point) {
        return 0;
      }
    }
    
    return 1;
  }
  
  # Interfaces
  static method interfaces : int () {
    # Interface
    {
      my $point3d = Point3D->new;
      unless ($point3d isa Stringable) {
        return 0;
      }
      unless ($point3d isa Cloneable) {
        return 0;
      }
    }

    # Cloneable
    {
      my $point3d = Point3D->new(1, 2, 3);
      my $cloneable = (Cloneable)$point3d;
      my $point3d_clone = (Point3D)$cloneable->clone;
      unless ($point3d_clone->x == $point3d->x && $point3d_clone->y == $point3d->y && $point3d_clone->z == $point3d->z) {
        return 0;
      }
      
      if ($point3d_clone == $point3d) {
        return 0;
      }
    }
    
    return 1;
  }
  
  # Fields
  static method fields : int () {
    
    {
      my $Point3D3d = Point3D->new(1, 2, 3);
      unless ($Point3D3d isa Point3D) {
        return 0;
      }
      
      unless ($Point3D3d->x == 1) {
        return 0;
      }
      
      unless ($Point3D3d->y == 2) {
        return 0;
      }
      
      unless ($Point3D3d->z == 3) {
        return 0;
      }
    }
    
    return 1;
  }
  
  # Class methods
  static method new : int () {
    {
      my $point3d = Point3D->new;
      unless ($point3d isa Point3D) {
        return 0;
      }
      unless ($point3d isa Point) {
        return 0;
      }
      
      unless ($point3d->x == 0) {
        return 0;
      }
      
      unless ($point3d->y == 0) {
        return 0;
      }
      unless ($point3d->z == 0) {
        return 0;
      }
    }

    {
      my $point3d = Point3D->new(1);
      unless ($point3d isa Point3D) {
        return 0;
      }
      unless ($point3d isa Point) {
        return 0;
      }
      
      unless ($point3d->x == 1) {
        return 0;
      }
      
      unless ($point3d->y == 0) {
        return 0;
      }
      unless ($point3d->z == 0) {
        return 0;
      }
    }

    {
      my $point3d = Point3D->new(1, 2);
      unless ($point3d isa Point3D) {
        return 0;
      }
      unless ($point3d isa Point) {
        return 0;
      }
      
      unless ($point3d->x == 1) {
        return 0;
      }
      
      unless ($point3d->y == 2) {
        return 0;
      }
      unless ($point3d->z == 0) {
        return 0;
      }
    }
    

    {
      my $point3d = Point3D->new(1, 2, 3);
      unless ($point3d isa Point3D) {
        return 0;
      }
      unless ($point3d isa Point) {
        return 0;
      }
      
      unless ($point3d->x == 1) {
        return 0;
      }
      
      unless ($point3d->y == 2) {
        return 0;
      }
      unless ($point3d->z == 3) {
        return 0;
      }
    }
    return 1;
  }
  
  # Instance methods
  static method clear : int () {
    {
      my $point3d = Point3D->new(1, 2, 3);
      $point3d->clear;
      unless ($point3d->x == 0) {
        return 0;
      }
      
      unless ($point3d->y == 0) {
        return 0;
      }
      unless ($point3d->z == 0) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method to_string : int () {
    {
      my $point3d = Point3D->new(1, 2, 3);
      unless ($point3d->to_string eq "(1,2,3)") {
        return 0;
      }
    }
    
    return 1;
  }
  
  # Extra
  static method extra : int () {
    # Basic
    {
      my $point3d = Point3D->new(1, 2, 3);
      unless ($point3d isa Point3D) {
        return 0;
      }
      unless ($point3d isa Point) {
        return 0;
      }
      
      unless ($point3d->x == 1) {
        return 0;
      }
      
      unless ($point3d->y == 2) {
        return 0;
      }

      unless ($point3d->z == 3) {
        return 0;
      }

      my $string = $point3d->to_string;
      unless ($string eq "(1,2,3)") {
        return 0;
      }
      
      $point3d->clear;
      unless ($point3d->x == 0 && $point3d->y == 0 && $point3d->z == 0) {
        return 0;
      }
    }
    
    # Assign and cast
    {
      my $point3d = Point3D->new(1, 2, 3);
      my $point = (Point)$point3d;
      $point->clear;
      unless ($point3d->x == 0) {
        return 0;
      }
      
      unless ($point3d->y == 0) {
        return 0;
      }
      unless ($point3d->z == 0) {
        return 0;
      }
      
      unless ($point isa Point3D) {
        return 0;
      }
      
      my $point_string = $point->to_string;
      unless ($point_string eq "(0,0,0)") {
        return 0;
      }
      
      my $point3d_string = $point->(Stringable)->to_string;
      unless ($point3d_string eq "(0,0,0)") {
        return 0;
      }
      
      {
        my $point3d_2 = (Point3D)$point;
        $point3d_2->clear;
        unless ($point3d->x == 0) {
          return 0;
        }
        
        unless ($point3d->y == 0) {
          return 0;
        }
        unless ($point3d->z == 0) {
          return 0;
        }
      }
    
      
      {
        my $point = Point->new;
        eval { (Point3D)$point; };
        unless ($@) {
          return 0;
        }
      }
      
      {
        my $point3d_array : Point3D[] = new Point3D[4];
        (Point[])$point3d_array;
        
        my $point_array : Point[] = new Point[3];
        
        $point_array = $point3d_array;

        my $foo = (Point3D[])$point_array;
      }

      {
        my $point3d_array : Point3D[] = new Point3D[4];
        (Point[])$point3d_array;
        
        my $point_array : Point[] = new Point[3];
        
        $point_array = $point3d_array;

        my $foo = (Point3D[])$point_array;
      }
      
      eval { (Point3D[])new Point[3]; };
      unless ($@) {
        return 0;
      }

      (Point[][])new Point3D[][3];
      
      eval { (Point3D[][])new Point[][3]; };
      unless ($@) {
        return 0;
      }
      
      {
        my $point3d = Point3D->new(1, 2, 3);
        my $point = (Point)$point3d;
        $point->Point::clear;
        unless ($point3d->x == 0) {
          return 0;
        }
        
        unless ($point3d->y == 0) {
          return 0;
        }
        unless ($point3d->z == 3) {
          return 0;
        }
        
        my $point_string = $point->Point::to_string;
        unless ($point_string eq "(0,0)") {
          return 0;
        }
      }
    }
    
    
    $@ = undef;
    
    return 1;
  }
  
  static method eq : int () {
    
    {
      my $point = Point3D->new;
      
      unless ($point isa EqualityCheckable) {
        return 0;
      }
      
      {
        my $ret = $point->eq(Point3D->new(1, 2, 3), Point3D->new(1, 2, 4));
        unless ($ret == 0) {
          return 0;
        }
      }
      
      {
        my $ret = $point->eq(Point3D->new(1, 2, 3), Point3D->new(1, 2, 3));
        unless ($ret == 1) {
          return 0;
        }
      }
      
      {
        my $ret = $point->eq(undef, undef);
        unless ($ret == 1) {
          return 0;
        }
      }
      
      {
        my $ret = $point->eq(undef, Point3D->new);
        unless ($ret == 0) {
          return 0;
        }
      }
      
      {
        my $ret = $point->eq(Point3D->new, undef);
        unless ($ret == 0) {
          return 0;
        }
      }
    }
    
    return 1;
  }
}
