class TestCase::Operator::Unsigned {
  use Fn;

  static method byte_object_signed : int () {
    my $val = (byte)-1; 
    my $obj = Byte->new($val);

    unless ($obj->unsigned == 0) {
      return 0;
    }
    unless ($obj->value == -1) {
      return 0;
    }
    unless ((int)$obj == -1) {
      return 0;
    }
    unless ((string)$obj eq "-1") {
      return 0;
    }

    # Read-only test
    $obj->make_read_only;
    unless ($obj->is_read_only == 1) {
      return 0;
    }
    eval {
      $obj->set_value(20);
    };
    unless ($@) {
      return 0;
    }

    return 1;
  }

  static method byte_object_unsigned : int () {
    my $val = (byte)-1; 
    
    # Test new_unsigned
    {
      my $obj = Byte->new_unsigned($val);
      unless ($obj->unsigned == 1) {
        return 0;
      }
      unless ($obj->value == 255) {
        return 0;
      }
      unless ((int)$obj == 255) {
        return 0;
      }
      unless ((string)$obj eq "255") {
        return 0;
      }
    }

    # Test set_unsigned
    {
      my $obj = Byte->new($val);
      $obj->set_unsigned(1);
      unless ($obj->unsigned == 1) {
        return 0;
      }
      unless ($obj->value == 255) {
        return 0;
      }
      unless ((int)$obj == 255) {
        return 0;
      }
    }

    # Clone test
    {
      my $obj = Byte->new_unsigned($val);
      my $clone = $obj->clone;
      unless ($clone->unsigned == 1) {
        return 0;
      }
      unless ($clone->value == 255) {
        return 0;
      }
    }

    # to_string test
    {
      my $obj = Byte->new_unsigned($val);
      unless ($obj->to_string eq "255") {
        return 0;
      }
    }
    
    # Test Fn->to_byte_object_unsigned
    {
      my $obj = Fn->to_byte_object_unsigned("255");
      unless ($obj->unsigned == 1) {
        return 0;
      }
      unless ($obj->value == 255) {
        return 0;
      }
      unless ((string)$obj eq "255") {
        return 0;
      }
    }

    return 1;
  }
  
  static method short_object_signed : int () {
    my $val = (short)-1;
    my $obj = Short->new($val);

    unless ($obj->unsigned == 0) {
      return 0;
    }
    unless ($obj->value == -1) {
      return 0;
    }
    unless ((int)$obj == -1) {
      return 0;
    }
    unless ((string)$obj eq "-1") {
      return 0;
    }

    # Read-only test
    $obj->make_read_only;
    unless ($obj->is_read_only == 1) {
      return 0;
    }
    eval {
      $obj->set_value((short)20);
    };
    unless ($@) {
      return 0;
    }
    

    return 1;
  }

  static method short_object_unsigned : int () {
    my $val = (short)-1;

    # Test new_unsigned
    {
      my $obj = Short->new_unsigned($val);
      unless ($obj->unsigned == 1) {
        return 0;
      }
      unless ($obj->value == 65535) {
        return 0;
      }
      unless ((int)$obj == 65535) {
        return 0;
      }
      unless ((string)$obj eq "65535") {
        return 0;
      }
    }

    # Test set_unsigned
    {
      my $obj = Short->new($val);
      $obj->set_unsigned(1);
      unless ($obj->unsigned == 1) {
        return 0;
      }
      unless ($obj->value == 65535) {
        return 0;
      }
      unless ((int)$obj == 65535) {
        return 0;
      }
    }

    # Clone test
    {
      my $obj = Short->new_unsigned($val);
      my $clone = $obj->clone;
      unless ($clone->unsigned == 1) {
        return 0;
      }
      unless ($clone->value == 65535) {
        return 0;
      }
    }

    # to_string test
    {
      my $obj = Short->new_unsigned($val);
      unless ($obj->to_string eq "65535") {
        return 0;
      }
    }
    
    # Test Fn->to_short_object_unsigned
    {
      my $obj = Fn->to_short_object_unsigned("65535");
      unless ($obj->unsigned == 1) {
        return 0;
      }
      unless ($obj->value == 65535) {
        return 0;
      }
      unless ((string)$obj eq "65535") {
        return 0;
      }
    }

    return 1;
  }
  
  static method int_object_signed : int () {
    my $val = -1;
    my $obj = Int->new($val);

    unless ($obj->unsigned == 0) {
      return 0;
    }
    unless ($obj->value == -1) {
      return 0;
    }
    unless ((int)$obj == -1) {
      return 0;
    }
    unless ((string)$obj eq "-1") {
      return 0;
    }

    # Read-only test
    $obj->make_read_only;
    unless ($obj->is_read_only == 1) {
      return 0;
    }
    eval {
      $obj->set_value(20);
    };
    unless ($@) {
      return 0;
    }

    return 1;
  }

  static method int_object_unsigned : int () {
    my $val = -1;

    # Test new_unsigned
    {
      my $obj = Int->new_unsigned($val);
      unless ($obj->unsigned == 1) {
        diag;
        return 0;
      }
      unless ($obj->value == -1) {
        diag $obj->value;
        return 0;
      }
      unless ((long)$obj == 4294967295L) {
        diag;
        return 0;
      }
      unless ((string)$obj eq "4294967295") {
        diag;
        return 0;
      }
    }

    # Test set_unsigned
    {
      my $obj = Int->new($val);
      $obj->set_unsigned(1);
      unless ($obj->unsigned == 1) {
        diag;
        return 0;
      }
      unless ($obj->value == -1) {
        diag;
        return 0;
      }
      unless ((long)$obj == 4294967295L) {
        diag;
        return 0;
      }
    }

    # Clone test
    {
      my $obj = Int->new_unsigned($val);
      my $clone = $obj->clone;
      unless ($clone->unsigned == 1) {
        diag;
        return 0;
      }
      unless ($clone->value == -1) {
        diag;
        return 0;
      }
    }

    # to_string test
    {
      my $obj = Int->new_unsigned($val);
      unless ($obj->to_string eq "4294967295") {
        diag;
        return 0;
      }
    }
    
    # Test Fn->to_int_object_unsigned
    {
      my $obj = Fn->to_int_object_unsigned("4294967295");
      unless ($obj->unsigned == 1) {
        return 0;
      }
      unless ($obj->value == -1) {
        return 0;
      }
      unless ((string)$obj eq "4294967295") {
        return 0;
      }
    }

    return 1;
  }
  
  static method long_object_signed : int () {
    my $val = -1L;
    my $obj = Long->new($val);

    unless ($obj->unsigned == 0) {
      return 0;
    }
    unless ($obj->value == -1L) {
      return 0;
    }
    unless ((long)$obj == -1L) {
      return 0;
    }
    unless ((string)$obj eq "-1") {
      return 0;
    }

    # Read-only test
    $obj->make_read_only;
    unless ($obj->is_read_only == 1) {
      return 0;
    }
    eval {
      $obj->set_value(20L);
    };
    unless ($@) {
      return 0;
    }

    return 1;
  }

  static method long_object_unsigned : int () {
    my $val = -1L;

    # Test new_unsigned
    {
      my $obj = Long->new_unsigned($val);
      unless ($obj->unsigned == 1) {
        return 0;
      }
      # The value is treated as bit pattern, but stored in long. 
      # In SPVM, Long->value returns long (signed), so it remains -1L.
      # However, string conversion and unsigned-aware logic should treat it as 18446744073709551615.
      unless ($obj->value == -1L) {
        return 0;
      }
      unless ((string)$obj eq "18446744073709551615") {
        return 0;
      }
    }

    # Test set_unsigned
    {
      my $obj = Long->new($val);
      $obj->set_unsigned(1);
      unless ($obj->unsigned == 1) {
        return 0;
      }
      unless ((string)$obj eq "18446744073709551615") {
        return 0;
      }
    }

    # Clone test
    {
      my $obj = Long->new_unsigned($val);
      my $clone = $obj->clone;
      unless ($clone->unsigned == 1) {
        return 0;
      }
      unless ((string)$clone eq "18446744073709551615") {
        return 0;
      }
    }

    # to_string test
    {
      my $obj = Long->new_unsigned($val);
      unless ($obj->to_string eq "18446744073709551615") {
        return 0;
      }
    }
    
    # Test Fn->to_long_object_unsigned
    {
      my $obj = Fn->to_long_object_unsigned("18446744073709551615");
      unless ($obj->unsigned == 1) {
        return 0;
      }
      unless ($obj->value == -1L) {
        return 0;
      }
      unless ((string)$obj eq "18446744073709551615") {
        return 0;
      }
    }

    return 1;
  }
  
}
