class TestCase::Lib::Fn3 {
  use Unicode as Un;
  use TestCase::Minimal;
  use Fn;
  use TestCase::Minimal;
  use EqualityChecker;
  use EqualityChecker::SameObject;
  use Fn;
  use TestCase::Minimal;
  use TestCase::Minimal;
  use EqualityChecker;
  use EqualityChecker::SameObject;
  use Fn;
  use TestCase::Minimal;
  use EqualityChecker;
  use EqualityChecker::SameObject;
  use Complex_2d;
  use Time;

  static method abs : int () {
    
    # Positive values
    {
      my $num = 3;
      my $ret = Fn->abs($num);
      unless ($ret isa int) {
        return 0;
      }
      unless ($ret == 3) {
        return 0;
      }
    }
    
    # Negative values
    {
      my $num = -3;
      my $ret = Fn->abs($num);
      unless ($ret == 3) {
        return 0;
      }
      
    }

    # Zeros
    {
      my $num = 0;
      my $ret = Fn->abs($num);
      unless ($ret == 0) {
        return 0;
      }
    }
    
    return 1;
  }

  static method labs : int () {
    
    # Positive values
    {
      my $num = 3L;
      my $ret = Fn->labs($num);
      unless ($ret isa long) {
        return 0;
      }
      unless ($ret == 3) {
        return 0;
      }
    }
    
    # Negative values
    {
      my $num = -3L;
      my $ret = Fn->labs($num);
      unless ($ret == 3) {
        return 0;
      }
      
    }

    # Zeros
    {
      my $num = 0;
      my $ret = Fn->labs($num);
      unless ($ret == 0) {
        return 0;
      }
    }
    
    return 1;
  }

  static method crand : int () {
    
    my $founds_plus = new int[10];
    my $founds_minus = new int[10];
    my $rand = 0;
    my $seed = (int)Time->time;
    for (my $i = 0; $i < 100000; $i++) {
      $rand = Fn->crand(\$seed);
      my $dig0 = $rand % 10;
      $founds_plus->[$dig0] = 1;
    }
    
    unless (Fn->equals_array_int($founds_plus, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1])) {
      return 0;
    }

    return 1;
  }

  static method rand : int () {
    
    # 0 <= random_number < 1
    {
      my $rand = 0.0;
      my $invalid_range = 0;
      my $seed = (int)Time->time;
      for (my $i = 0; $i < 100000; $i++) {
        $rand = Fn->rand(\$seed);
        
        unless ($rand >= 0 && $rand < 1) {
          $invalid_range = 1;
          last;
        }
      }
      
      if ($invalid_range) {
        return 0;
      }
    }
    
    # Apper random numbers
    {
      my $founds_plus = new int[10];
      my $founds_minus = new int[10];
      my $rand = 0.0;
      my $seed = (int)Time->time;
      for (my $i = 0; $i < 100000; $i++) {
        $rand = Fn->rand(\$seed);
        
        # 0-9
        my $dig0 = (int)($rand * 10);
        $founds_plus->[$dig0] = 1;
      }
      
      unless (Fn->equals_array_int($founds_plus, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1])) {
        return 0;
      }
    }

    return 1;
  }

  static method RAND_MAX : int () {
    
    unless (Fn->RAND_MAX > 0) {
      return 1;
    }

    return 1;
  }

  static method byte_constant : int () {
    if ((int)Fn->INT8_MIN() == (int)(byte)-128) {
      if ((int)Fn->INT8_MAX() == (int)(byte)127) {
        return 1;
      }
    }

    return 0;
  }

  static method short_constant : int () {
    if ((int)Fn->INT16_MIN() == (int)(short)-32768) {
      if ((int)Fn->INT16_MAX() == (int)(short)32767) {
        return 1;
      }
    }

    return 0;
  }

  static method int_constant : int () {
    if (Fn->INT32_MIN() == -2147483648) {
      if (Fn->INT32_MAX() == 2147483647) {
        return 1;
      }
    }

    return 0;
  }

  static method long_constant : int () {
    if (Fn->INT64_MIN() == -9223372036854775808L) {
      if (Fn->INT64_MAX() == 9223372036854775807L) {
        return 1;
      }
    }

    return 0;
  }

  static method copy_str : int () {
    my $string = "abc";
    my $string_out = Fn->copy_string($string);

    unless ($string_out eq "abc") {
      return 0;
    }

    return 1;
  }
  
  static method hex : int () {
    # 0
    {
      my $hex_string = (string)"0";
      my $hex_num = Fn->hex($hex_string);
      unless ($hex_num isa int) {
        return 0;
      }
      unless ($hex_num == 0) {
        return 0;
      }
    }

    # 1-9
    {
      unless (Fn->hex("1") == 1) { return 0; }
      unless (Fn->hex("2") == 2) { return 0; }
      unless (Fn->hex("3") == 3) { return 0; }
      unless (Fn->hex("4") == 4) { return 0; }
      unless (Fn->hex("5") == 5) { return 0; }
      unless (Fn->hex("6") == 6) { return 0; }
      unless (Fn->hex("7") == 7) { return 0; }
      unless (Fn->hex("8") == 8) { return 0; }
      unless (Fn->hex("9") == 9) { return 0; }
    }

    # a-z
    {
      unless (Fn->hex("a") == 10) { return 0; }
      unless (Fn->hex("b") == 11) { return 0; }
      unless (Fn->hex("c") == 12) { return 0; }
      unless (Fn->hex("d") == 13) { return 0; }
      unless (Fn->hex("e") == 14) { return 0; }
      unless (Fn->hex("f") == 15) { return 0; }
    }

    # A-Z
    {
      unless (Fn->hex("A") == 10) { return 0; }
      unless (Fn->hex("B") == 11) { return 0; }
      unless (Fn->hex("C") == 12) { return 0; }
      unless (Fn->hex("D") == 13) { return 0; }
      unless (Fn->hex("E") == 14) { return 0; }
      unless (Fn->hex("F") == 15) { return 0; }
    }

    # 19afAF25
    {
      unless (Fn->hex("19afAF25") == 430944037) { return 0; }
      unless (Fn->hex("19afAF25") == 430944037) { return 0; }
    }

    # FFFFFFFF
    {
      unless (Fn->hex("FFFFFFFF") == 0xFFFFFFFF) { return 0; }
    }
    
    # Exception - undef
    {
      eval { Fn->hex(undef); };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Empty String
    {
      eval { Fn->hex(""); };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Invalid hex string
    {
      eval { Fn->hex("g"); };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Too long
    {
      eval { Fn->hex("111111111"); };
      unless ($@) {
        return 0;
      }
    }
    
    $@ = undef;
    
    return 1;
  }
  
  static method trim_ascii_space : int () {
    # undef
    {
      my $string = (string)undef;
      my $trimed_string = Fn->trim_ascii_space($string);
      unless ($trimed_string == undef) {
        return 0;
      }
    }
    
    # no left and right spaces
    {
      my $string = (string)"ab  c";
      my $trimed_string = Fn->trim_ascii_space($string);
      unless ($trimed_string eq "ab  c") {
        return 0;
      }
    }

    # left spaces
    {
      my $string = (string)"  \t  \nab  c";
      my $trimed_string = Fn->trim_ascii_space($string);
      unless ($trimed_string eq "ab  c") {
        return 0;
      }
    }

    # right spaces
    {
      my $string = (string)"ab  c  \t  \n";
      my $trimed_string = Fn->trim_ascii_space($string);
      unless ($trimed_string eq "ab  c") {
        return 0;
      }
    }

    # left and right spaces
    {
      my $string = (string)"  \t  \nab  c  \t  \n";
      my $trimed_string = Fn->trim_ascii_space($string);
      unless ($trimed_string eq "ab  c") {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method split : int () {
    {
      my $string = "foo,bar,baz";
      my $split_strs = Fn->split(",", $string);
      unless (Fn->equals_array_string($split_strs, ["foo", "bar", "baz"])) {
        return 0;
      }
    }

    {
      my $string = "foo,bar,";
      my $split_strs = Fn->split(",", $string);
      unless (Fn->equals_array_string($split_strs, ["foo", "bar", ""])) {
        return 0;
      }
    }

    {
      my $string = ",foo,,bar,,";
      my $split_strs = Fn->split(",", $string);
      unless (Fn->equals_array_string($split_strs, ["", "foo", "", "bar", "", ""])) {
        return 0;
      }
    }

    {
      my $string = "foo : bar : baz";
      my $split_strs = Fn->split(" : ", $string);
      unless (Fn->equals_array_string($split_strs, ["foo", "bar", "baz"])) {
        return 0;
      }
    }
    {
      my $string = "foo : bar : ";
      my $split_strs = Fn->split(" : ", $string);
      unless (Fn->equals_array_string($split_strs, ["foo", "bar", ""])) {
        return 0;
      }
    }
    {
      my $string = " : foo :  : bar :  : ";
      my $split_strs = Fn->split(" : ", $string);
      unless (Fn->equals_array_string($split_strs, ["", "foo", "", "bar", "", ""])) {
        return 0;
      }
    }

    {
      my $string = "foo---bar---baz";
      my $split_strs = Fn->split("---", $string);
      unless (Fn->equals_array_string($split_strs, ["foo", "bar", "baz"])) {
        return 0;
      }
    }
    {
      my $string = "foo---bar---";
      my $split_strs = Fn->split("---", $string);
      unless (Fn->equals_array_string($split_strs, ["foo", "bar", ""])) {
        return 0;
      }
    }
    {
      my $string = "---foo------bar------";
      my $split_strs = Fn->split("---", $string);
      unless (Fn->equals_array_string($split_strs, ["", "foo", "", "bar", "", ""])) {
        return 0;
      }
    }

    {
      my $string = "foo--!bar---baz";
      my $split_strs = Fn->split("---", $string);
      unless (Fn->equals_array_string($split_strs, ["foo--!bar", "baz"])) {
        return 0;
      }
    }
    return 1;
  }

  static method chompr : int () {
    {
      my $string = "abc\n";
      my $ret = Fn->chompr($string);
      unless ($ret eq "abc") {
        return 0;
      }
    }
    {
      my $string = "abc";
      my $ret = Fn->chompr($string);
      unless ($ret eq "abc") {
        return 0;
      }
    }
    {
      my $string = "";
      my $ret = Fn->chompr($string);
      unless ($ret eq "") {
        return 0;
      }
    }

    return 1;
  }
  
  static method is_alnum : int () {

    my $ok = 1;
    for (my $i = 0; $i < 128; $i++) {
      my $char = $i;

      if (($char >= 'A' && $char <= 'Z') || ($char >= 'a' && $char <= 'z') || ($char >= '0' && $char <= '9')) {
        my $ret = Fn->is_alnum($char);
        unless ($ret == 1) {
          $ok = 0;
        }
      }
      else {
        my $ret = Fn->is_alnum($char);
        unless ($ret == 0) {
          $ok = 0;
        }
      }
    }

    unless ($ok) {
      return 0;
    }

    return 1;
  }

  static method is_alpha : int () {

    my $ok = 1;
    for (my $i = 0; $i < 128; $i++) {
      my $char = $i;

      if (($char >= 'A' && $char <= 'Z') || ($char >= 'a' && $char <= 'z')) {
        my $ret = Fn->is_alpha($char);
        unless ($ret == 1) {
          $ok = 0;
        }
      }
      else {
        my $ret = Fn->is_alpha($char);
        unless ($ret == 0) {
          $ok = 0;
        }
      }
    }

    unless ($ok) {
      return 0;
    }

    return 1;
  }

  static method is_blank : int () {

    my $ok = 1;
    for (my $i = 0; $i < 128; $i++) {
      my $char = $i;

      if ($char >= ' ' ||  $char <= '\t') {
        my $ret = Fn->is_blank($char);
        unless ($ret == 1) {
          $ok = 0;
        }
      }
      else {
        my $ret = Fn->is_blank($char);
        unless ($ret == 0) {
          $ok = 0;
        }
      }
    }

    unless ($ok) {
      return 0;
    }

    return 1;
  }

  static method is_cntrl : int () {

    my $ok = 1;
    for (my $i = 0; $i < 128; $i++) {
      my $char = $i;

      if (($char >= 0x00 && $char <= 0x1f) || $char == 0x7f) {
        my $ret = Fn->is_cntrl($char);
        unless ($ret == 1) {
          $ok = 0;
        }
      }
      else {
        my $ret = Fn->is_cntrl($char);
        unless ($ret == 0) {
          $ok = 0;
        }
      }
    }

    unless ($ok) {
      return 0;
    }

    return 1;
  }

  static method is_digit : int () {

    my $ok = 1;
    for (my $i = 0; $i < 128; $i++) {
      my $char = $i;

      if ($char >= '0' && $char <= '9') {
        my $ret = Fn->is_digit($char);
        unless ($ret == 1) {
          $ok = 0;
        }
      }
      else {
        my $ret = Fn->is_digit($char);
        unless ($ret == 0) {
          $ok = 0;
        }
      }
    }

    unless ($ok) {
      return 0;
    }

    return 1;
  }

  static method is_graph : int () {

    my $ok = 1;
    for (my $i = 0; $i < 128; $i++) {
      my $char = $i;

      if ($char >= 0x21 && $char <= 0x7e) {
        my $ret = Fn->is_graph($char);
        unless ($ret == 1) {
          $ok = 0;
        }
      }
      else {
        my $ret = Fn->is_graph($char);
        unless ($ret == 0) {
          $ok = 0;
        }
      }
    }

    unless ($ok) {
      return 0;
    }

    return 1;
  }

  static method is_lower : int () {

    my $ok = 1;
    for (my $i = 0; $i < 128; $i++) {
      my $char = $i;

    if ($char >= 'a' && $char <= 'z') {
        my $ret = Fn->is_lower($char);
        unless ($ret == 1) {
          $ok = 0;
        }
      }
      else {
        my $ret = Fn->is_lower($char);
        unless ($ret == 0) {
          $ok = 0;
        }
      }
    }

    unless ($ok) {
      return 0;
    }

    return 1;
  }

  static method is_print : int () {

    my $ok = 1;
    for (my $i = 0; $i < 128; $i++) {
      my $char = $i;

      if ($char >= 0x20 && $char <= 0x7e) {
        my $ret = Fn->is_print($char);
        unless ($ret == 1) {
          $ok = 0;
        }
      }
      else {
        my $ret = Fn->is_print($char);
        unless ($ret == 0) {
          $ok = 0;
        }
      }
    }

    unless ($ok) {
      return 0;
    }

    return 1;
  }

  static method is_punct : int () {

    my $ok = 1;
    for (my $i = 0; $i < 128; $i++) {
      my $char = $i;

      if (($char >= 0x21 && $char <= 0x2f) || ($char >= 0x3a && $char <= 0x40) || ($char >= 0x5b && $char <= 0x60) || ($char >= 0x7b && $char <= 0x7e)) {
        my $ret = Fn->is_punct($char);
        unless ($ret == 1) {
          $ok = 0;
        }
      }
      else {
        my $ret = Fn->is_punct($char);
        unless ($ret == 0) {
          $ok = 0;
        }
      }
    }

    unless ($ok) {
      return 0;
    }

    return 1;
  }

  static method is_space : int () {

    my $ok = 1;
    for (my $i = 0; $i < 128; $i++) {
      my $char = $i;

      if (($char >= 0x09 && $char <= 0x0d) || $char == 0x20) {
        my $ret = Fn->is_space($char);
        unless ($ret == 1) {
          $ok = 0;
        }
      }
      else {
        my $ret = Fn->is_space($char);
        unless ($ret == 0) {
          $ok = 0;
        }
      }
    }

    unless ($ok) {
      return 0;
    }

    return 1;
  }

  static method is_upper : int () {

    my $ok = 1;
    for (my $i = 0; $i < 128; $i++) {
      my $char = $i;

      if ($char >= 'A' && $char <= 'Z') {
        my $ret = Fn->is_upper($char);
        unless ($ret == 1) {
          $ok = 0;
        }
      }
      else {
        my $ret = Fn->is_upper($char);
        unless ($ret == 0) {
          $ok = 0;
        }
      }
    }

    unless ($ok) {
      return 0;
    }

    return 1;
  }

  static method is_xdigit : int () {

    my $ok = 1;
    for (my $i = 0; $i < 128; $i++) {
      my $char = $i;

      if (($char >= 'A' && $char <= 'F') || ($char >= 'a' && $char <= 'f') || ($char >= '0' && $char <= '9')) {
        my $ret = Fn->is_xdigit($char);
        unless ($ret == 1) {
          $ok = 0;
        }
      }
      else {
        my $ret = Fn->is_xdigit($char);
        unless ($ret == 0) {
          $ok = 0;
        }
      }
    }

    unless ($ok) {
      return 0;
    }

    return 1;
  }

  static method to_lower : int () {

    my $ok = 1;
    for (my $i = 0; $i < 128; $i++) {
      my $char = $i;

      if ($char >= 'A' && $char <= 'Z') {
        my $ret = Fn->to_lower($char);
        unless ($ret == $char + 0x20) {
          $ok = 0;
        }
      }
      else {
        my $ret = Fn->to_lower($char);
        unless ($ret == $char) {
          $ok = 0;
        }
      }
    }

    unless ($ok) {
      return 0;
    }

    return 1;
  }

  static method to_upper : int () {

    my $ok = 1;
    for (my $i = 0; $i < 128; $i++) {
      my $char = $i;

    if ($char >= 'a' && $char <= 'z') {
        my $ret = Fn->to_upper($char);
        unless ($ret == $char - 0x20) {
          $ok = 0;
        }
      }
      else {
        my $ret = Fn->to_upper($char);
        unless ($ret == $char) {
          $ok = 0;
        }
      }
    }

    unless ($ok) {
      return 0;
    }

    return 1;
  }

  static method is_perl_space : int () {

    my $ok = 1;
    for (my $i = 0; $i < 128; $i++) {
      my $char = $i;

      if ($char == ' ' || $char == '\r' || $char == '\n' || $char == '\t' || $char == '\f') {
        my $ret = Fn->is_perl_space($char);
        unless ($ret == 1) {
          $ok = 0;
        }
      }
      else {
        my $ret = Fn->is_perl_space($char);
        unless ($ret == 0) {
          $ok = 0;
        }
      }
    }

    unless ($ok) {
      return 0;
    }

    return 1;
  }

  static method is_perl_word : int () {

    my $ok = 1;
    for (my $i = 0; $i < 128; $i++) {
      my $char = $i;

      if ($char >= 'a' && $char <= 'z' || $char >= 'A' && $char <= 'Z' || $char == '_' || $char >= '0' && $char <= '9') {
        my $ret = Fn->is_perl_word($char);
        unless ($ret == 1) {
          $ok = 0;
        }
      }
      else {
        my $ret = Fn->is_perl_word($char);
        unless ($ret == 0) {
          $ok = 0;
        }
      }
    }

    unless ($ok) {
      return 0;
    }

    return 1;
  }

  static method to_int : int () {
    # 10 digit minimal and return type is int
    {
      my $string = "-2147483648";
      my $num = Fn->to_int($string);
      unless ($num isa int) {
        return 0;
      }

      unless ($num == -2147483648) {
        return 0;
      }
    }
    
    return 1;
  }

  static method to_int_with_base : int () {
    # 10 digit minimal and return type is int
    {
      my $string = "-2147483648";
      my $num = Fn->to_int_with_base($string, 10);
      unless ($num isa int) {
        return 0;
      }

      unless ($num == -2147483648) {
        return 0;
      }
    }

    # 10 digit max
    {
      my $string = "2147483647";
      my $num = Fn->to_int_with_base($string, 10);
      unless ($num isa int) {
        return 0;
      }

      unless ($num == 2147483647) {
        return 0;
      }
    }

    # 2 digit
    {
      my $string = "11";
      my $num = Fn->to_int_with_base($string, 2);

      unless ($num == 3) {
        return 0;
      }
    }

    # 8 digit
    {
      my $string = "11";
      my $num = Fn->to_int_with_base($string, 8);

      unless ($num == 9) {
        return 0;
      }
    }

    # 16 digit
    {
      my $string = "FF";
      my $num = Fn->to_int_with_base($string, 16);

      unless ($num == 255) {
        return 0;
      }
    }

    # Invalid string format
    {
      my $string = "10oppp";
      eval {
        Fn->to_int_with_base($string, 10);
      };
      unless ($@) {
        return 0;
      }
      $@ = undef;
    }

    # Invalid digit
    {
      my $string = "10";
      eval {
        Fn->to_int_with_base($string, 100);
      };
      unless ($@) {
        return 0;
      }
      $@ = undef;
    }

    # Out of range max + 1
    {
      my $string = "2147483648";
      eval {
        Fn->to_int_with_base($string, 10);
      };
      unless ($@) {
        return 0;
      }
      $@ = undef;
    }

    # Out of range min - 1
    {
      my $string = "-2147483649";
      eval {
        Fn->to_int_with_base($string, 10);
      };
      unless ($@) {
        return 0;
      }
      $@ = undef;
    }

    return 1;
  }

  static method to_long : int () {
    # 10 digit minimal and return type is int
    {
      my $string = "-9223372036854775808";
      my $num = Fn->to_long($string);
      unless ($num isa long) {
        return 0;
      }

      unless ($num == -9223372036854775808L) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method to_long_with_base : int () {
    # 10 digit minimal and return type is int
    {
      my $string = "-9223372036854775808";
      my $num = Fn->to_long_with_base($string, 10);
      unless ($num isa long) {
        return 0;
      }

      unless ($num == -9223372036854775808L) {
        return 0;
      }
    }

    # 10 digit max
    {
      my $string = "9223372036854775807";
      my $num = Fn->to_long_with_base($string, 10);

      unless ($num == 9223372036854775807L) {
        return 0;
      }
    }

    # 2 digit
    {
      my $string = "11";
      my $num = Fn->to_long_with_base($string, 2);

      unless ($num == 3) {
        return 0;
      }
    }

    # 8 digit
    {
      my $string = "11";
      my $num = Fn->to_long_with_base($string, 8);

      unless ($num == 9) {
        return 0;
      }
    }

    # 16 digit
    {
      my $string = "FF";
      my $num = Fn->to_long_with_base($string, 16);

      unless ($num == 255) {
        return 0;
      }
    }

    # Invalid string format
    {
      my $string = "10oppp";
      eval {
        Fn->to_long_with_base($string, 10);
      };
      unless ($@) {
        return 0;
      }
      $@ = undef;
    }

    # Invalid digit
    {
      my $string = "10";
      eval {
        Fn->to_long_with_base($string, 100);
      };
      unless ($@) {
        return 0;
      }
      $@ = undef;
    }

    # Out of range max + 1
    {
      my $string = "9223372036854775808";
      eval {
        Fn->to_long_with_base($string, 10);
      };
      unless ($@) {
        return 0;
      }
      $@ = undef;
    }

    # Out of range min - 1
    {
      my $string = "-9223372036854775809";
      eval {
        Fn->to_long_with_base($string, 10);
      };
      unless ($@) {
        return 0;
      }
      $@ = undef;
    }

    return 1;
  }

  static method to_float : int () {
    # 10 digit minimal and return type is int
    {
      my $string = "1.25";
      my $num = Fn->to_float($string);
      unless ($num isa float) {
        return 0;
      }

      unless ($num == 1.25) {
        return 0;
      }
    }

    # Invalid string format
    {
      my $string = "10.5oppp";
      eval {
        Fn->to_float($string);
      };
      unless ($@) {
        return 0;
      }
      $@ = undef;
    }

    return 1;
  }

  static method to_double : int () {
    # 10 digit minimal and return type is int
    {
      my $string = "1.25";
      my $num = Fn->to_double($string);
      unless ($num isa double) {
        return 0;
      }

      unless ($num == 1.25) {
        return 0;
      }
    }

    # Invalid string format
    {
      my $string = "10.5oppp";
      eval {
        Fn->to_double($string);
      };
      unless ($@) {
        return 0;
      }
      $@ = undef;
    }

    return 1;
  }

  static method ucfirst : int () {
    {
      my $string = "@abc";
      my $result_str = Fn->ucfirst($string);
      unless ($result_str eq "@abc") {
        return 0;
      }
    }
    {
      my $string = "[abc";
      my $result_str = Fn->ucfirst($string);
      unless ($result_str eq "[abc") {
        return 0;
      }
    }

    {
      my $string = "aabc";
      my $result_str = Fn->ucfirst($string);
      unless ($result_str eq "Aabc") {
        return 0;
      }
    }

    {
      my $string = "pabc";
      my $result_str = Fn->ucfirst($string);
      unless ($result_str eq "Pabc") {
        return 0;
      }
    }

    {
      my $string = "zabc";
      my $result_str = Fn->ucfirst($string);
      unless ($result_str eq "Zabc") {
        return 0;
      }
    }
    return 1;
  }

  static method uc : int () {
    {
      my $string = "@[apz[";
      my $result_str = Fn->uc($string);
      unless ($result_str eq "@[APZ[") {
        return 0;
      }
    }
    return 1;
  }

  static method lc : int () {
    {
      my $string = "@[APZ[";
      my $result_str = Fn->lc($string);
      unless ($result_str eq "@[apz[") {
        return 0;
      }
    }
    return 1;
  }

  static method lcfirst : int () {
    {
      my $string = "@ABC";
      my $result_str = Fn->lcfirst($string);
      unless ($result_str eq "@ABC") {
        return 0;
      }
    }
    {
      my $string = "[ABC";
      my $result_str = Fn->lcfirst($string);
      unless ($result_str eq "[ABC") {
        return 0;
      }
    }

    {
      my $string = "AABC";
      my $result_str = Fn->lcfirst($string);
      unless ($result_str eq "aABC") {
        return 0;
      }
    }

    {
      my $string = "PABC";
      my $result_str = Fn->lcfirst($string);
      unless ($result_str eq "pABC") {
        return 0;
      }
    }

    {
      my $string = "ZABC";
      my $result_str = Fn->lcfirst($string);
      unless ($result_str eq "zABC") {
        return 0;
      }
    }
    return 1;
  }

  static method index : int () {

    {
      my $target = "abcde";
      my $search = "bcd";
      my $pos = Fn->index($target, $search, 0);
      unless ($pos == 1) {
        return 0;
      }
    }

    {
      my $target = "abcde";
      my $search = "bcd";
      my $pos = Fn->index($target, $search, 1);
      unless ($pos == 1) {
        return 0;
      }
    }

    {
      my $target = "abcde";
      my $search = "bcd";
      my $pos = Fn->index($target, $search, 2);
      unless ($pos == -1) {
        return 0;
      }
    }

    {
      my $target = "abcde";
      my $search = "pq";
      my $pos = Fn->index($target, $search, 2);
      unless ($pos == -1) {
        return 0;
      }
    }
    
    return 1;
  }

  static method index_len : int () {

    {
      my $target = "abcde";
      my $search = "bcd";
      my $pos = Fn->index_len($target, $search, 0, length $target);
      unless ($pos == 1) {
        return 0;
      }
    }

    {
      my $target = "abcde";
      my $search = "bcd";
      my $pos = Fn->index_len($target, $search, 0, length $target + 1);
      unless ($pos == 1) {
        return 0;
      }
    }

    {
      my $target = "abcde";
      my $search = "bcd";
      my $pos = Fn->index_len($target, $search, 0, 4);
      unless ($pos == 1) {
        return 0;
      }
    }

    {
      my $target = "abcde";
      my $search = "bcd";
      my $pos = Fn->index_len($target, $search, 0, 3);
      unless ($pos == -1) {
        return 0;
      }
    }

    {
      my $target = "abcde";
      my $search = "bcd";
      my $pos = Fn->index_len($target, $search, 1, length $target);
      unless ($pos == 1) {
        return 0;
      }
    }

    {
      my $target = "abcde";
      my $search = "bcd";
      my $pos = Fn->index_len($target, $search, 2, length $target);
      unless ($pos == -1) {
        return 0;
      }
    }

    {
      my $target = "abcde";
      my $search = "pq";
      my $pos = Fn->index_len($target, $search, 2, length $target);
      unless ($pos == -1) {
        return 0;
      }
    }
    
    return 1;
  }

  static method rindex : int () {

    {
      my $target = "abab";
      my $search = "ab";
      my $pos = Fn->rindex($target, $search, 3);
      unless ($pos == 2) {
        return 0;
      }
    }

    {
      my $target = "abab";
      my $search = "ab";
      my $pos = Fn->rindex($target, $search, 2);
      unless ($pos == 2) {
        return 0;
      }
    }

    {
      my $target = "abab";
      my $search = "ab";
      my $pos = Fn->rindex($target, $search, 1);
      unless ($pos == 0) {
        return 0;
      }
    }

    {
      my $target = "abab";
      my $search = "ab";
      my $pos = Fn->rindex($target, $search, 0);
      unless ($pos == 0) {
        return 0;
      }
    }

    {
      my $target = "abab";
      my $search = "pq";
      my $pos = Fn->rindex($target, $search, 2);
      unless ($pos == -1) {
        return 0;
      }
    }

    return 1;
  }

  static method rindex_len : int () {

    {
      my $target = "abab";
      my $search = "ab";
      my $pos = Fn->rindex_len($target, $search, 3, length $target);
      unless ($pos == 2) {
        return 0;
      }
    }

    {
      my $target = "abab";
      my $search = "ab";
      my $pos = Fn->rindex_len($target, $search, 3, length $target + 1);
      unless ($pos == 2) {
        return 0;
      }
    }

    {
      my $target = "abab";
      my $search = "ab";
      my $pos = Fn->rindex_len($target, $search, 2, length $target);
      unless ($pos == 2) {
        return 0;
      }
    }

    {
      my $target = "abab";
      my $search = "ab";
      my $pos = Fn->rindex_len($target, $search, 1, length $target);
      unless ($pos == 0) {
        return 0;
      }
    }

    {
      my $target = "abab";
      my $search = "ab";
      my $pos = Fn->rindex_len($target, $search, 0, length $target);
      unless ($pos == 0) {
        return 0;
      }
    }

    {
      my $target = "abab";
      my $search = "pq";
      my $pos = Fn->rindex_len($target, $search, 2, length $target);
      unless ($pos == -1) {
        return 0;
      }
    }

    {
      my $target = "abcab";
      my $search = "bca";
      my $pos = Fn->rindex_len($target, $search, length $target - 1, length $target);
      unless ($pos == 1) {
        return 0;
      }
    }

    {
      my $target = "abcab";
      my $search = "bca";
      my $pos = Fn->rindex_len($target, $search, 4 - 1, 4);
      unless ($pos == 1) {
        return 0;
      }
    }

    {
      my $target = "abcab";
      my $search = "bca";
      my $pos = Fn->rindex_len($target, $search, 3 - 1, 3);
      unless ($pos == -1) {
        return 0;
      }
    }

    return 1;
  }

  static method join : int () {
    my $strings = ["abc", "def", "hij"];

    my $dump = Fn->join(",", $strings);

    if ($dump eq "abc,def,hij") {
      return 1;
    }

    return 0;
  }

  static method copy_string : int () {
    # copy string
    {
      my $string = "abc";
      my $string_out = Fn->copy_string($string);
      
      # Equals the value
      unless ($string_out eq "abc") {
        return 0;
      }
      
      # Not equals address
      if ($string == $string_out) {
        return 0;
      }
    }
    
    # undef
    {
      my $string_out = Fn->copy_string(undef);
      
      # Equals the value
      unless ($string_out == undef) {
        return 0;
      }
    }

    return 1;
  }


  static method dump_array_byte : int () {
    # Dump array
    {
      my $nums = [(byte)1, 2, Fn->INT8_MIN()];

      my $dump = Fn->dump_array_byte($nums);
      
      unless ($dump eq "[\n  1,\n  2,\n  -128\n]") {
        return 0;
      }
    }

    # Dump undef
    {
      my $dump = Fn->dump_array_byte(undef);
      
      unless ($dump == undef) {
        return 0;
      }
    }

    return 1;
  }

  static method dump_array_short : int () {
    # Dump array
    {
      my $nums = [(short)1, 2, Fn->INT16_MIN()];

      my $dump = Fn->dump_array_short($nums);

      unless ($dump eq "[\n  1,\n  2,\n  -32768\n]") {
        return 0;
      }
    }
    
    # Dump undef
    {
      my $dump = Fn->dump_array_short(undef);
      
      unless ($dump == undef) {
        return 0;
      }
    }

    return 1;
  }

  static method dump_array_int : int () {
    # Dump array
    {
      my $nums = [(int)1, 2, Fn->INT32_MIN()];

      my $dump = Fn->dump_array_int($nums);

      unless ($dump eq "[\n  1,\n  2,\n  -2147483648\n]") {
        return 0;
      }
    }

    # Dump undef
    {
      my $dump = Fn->dump_array_int(undef);
      
      unless ($dump == undef) {
        return 0;
      }
    }


    return 1;
  }

  static method dump_array_long : int () {
    # Dump array
    {
      my $nums = [(long)1, 2, Fn->INT64_MIN()];

      my $dump = Fn->dump_array_long($nums);

      unless ($dump eq "[\n  1,\n  2,\n  -9223372036854775808\n]") {
        return 0;
      }
    }

    # Dump undef
    {
      my $dump = Fn->dump_array_long(undef);
      
      unless ($dump == undef) {
        return 0;
      }
    }


    return 1;
  }

  static method dump_array_float : int () {
    # Dump array
    {
      my $nums = [(float)1, 2, 2.45f];

      my $dump = Fn->dump_array_float($nums);

      unless ($dump eq "[\n  1,\n  2,\n  2.45\n]") {
        return 0;
      }
    }

    # Dump undef
    {
      my $dump = Fn->dump_array_float(undef);
      
      unless ($dump == undef) {
        return 0;
      }
    }

    return 1;
  }

  static method dump_array_double : int () {
    # Dump array
    {
      my $nums = [(double)1, 2, 2.45];

      my $dump = Fn->dump_array_double($nums);

      unless ($dump eq "[\n  1,\n  2,\n  2.45\n]") {
        return 0;
      }
    }

    # Dump undef
    {
      my $dump = Fn->dump_array_double(undef);
      
      unless ($dump == undef) {
        return 0;
      }
    }

    return 1;
  }

  static method dump_unsigned_array_byte : int () {
    # Dump array
    {
      my $nums = [(byte)1, 2, -1, Fn->UINT8_MAX];
      
      my $dump = Fn->dump_array_unsigned_byte($nums);
      
      unless ($dump eq "[\n  1,\n  2,\n  255,\n  255\n]") {
        return 0;
      }
    }

    # Dump undef
    {
      my $dump = Fn->dump_array_unsigned_byte(undef);
      
      unless ($dump == undef) {
        return 0;
      }
    }

    return 1;
  }

  static method dump_unsigned_array_short : int () {
    # Dump array
    {
      my $nums = [(short)1, 2, -1, Fn->UINT16_MAX];
      
      my $dump = Fn->dump_array_unsigned_short($nums);
      
      unless ($dump eq "[\n  1,\n  2,\n  65535,\n  65535\n]") {
        return 0;
      }
    }

    # Dump undef
    {
      my $dump = Fn->dump_array_unsigned_short(undef);
      
      unless ($dump == undef) {
        return 0;
      }
    }

    return 1;
  }

  static method dump_unsigned_array_int : int () {
    # Dump array
    {
      my $nums = [(int)1, 2, -1, Fn->UINT32_MAX];
      
      my $dump = Fn->dump_array_unsigned_int($nums);
      
      unless ($dump eq "[\n  1,\n  2,\n  4294967295,\n  4294967295\n]") {
        return 0;
      }
    }

    # Dump undef
    {
      my $dump = Fn->dump_array_unsigned_int(undef);
      
      unless ($dump == undef) {
        return 0;
      }
    }

    return 1;
  }

  static method dump_unsigned_array_long : long () {
    # Dump array
    {
      my $nums = [(long)1, 2, -1, Fn->UINT64_MAX];
      
      my $dump = Fn->dump_array_unsigned_long($nums);
      
      unless ($dump eq "[\n  1,\n  2,\n  18446744073709551615,\n  18446744073709551615\n]") {
        return 0;
      }
    }

    # Dump undef
    {
      my $dump = Fn->dump_array_unsigned_long(undef);
      
      unless ($dump == undef) {
        return 0;
      }
    }

    return 1;
  }

  static method dump_array_string : int () {
    # Dump array
    {
      my $strings = ["abc", "def", "ghi"];

      my $dump = Fn->dump_array_string($strings);

      unless ($dump eq "[\n  abc,\n  def,\n  ghi\n]") {
        return 0;
      }
    }

    # Dump undef
    {
      my $dump = Fn->dump_array_string(undef);
      
      unless ($dump == undef) {
        return 0;
      }
    }

    return 1;
  }

  static method dump_array_object : int () {
    
    {
      my $minimals = [
        TestCase::Minimal->new_xy(1, 2),
        TestCase::Minimal->new_xy(3, 4),
        TestCase::Minimal->new_xy(5, 6)
      ];

      my $dump = Fn->dump_array_object($minimals, method : string ($obj : object) {
        my $minimal = (TestCase::Minimal)$obj;
        my $x = $minimal->x;
        my $y = $minimal->y;
        my $str = "($x,$y)";
        return $str;
      });

      if ($dump eq "[\n  (1,2),\n  (3,4),\n  (5,6)\n]") {
        return 1;
      }
    }

    # Dump undef
    {
      my $dump = Fn->dump_array_object(undef, undef);
      
      unless ($dump == undef) {
        return 0;
      }
    }

    return 1;
  }

  static method is_array : int () {
    
    # Array
    {
      my $array = new byte[3];
      
      unless (Fn->is_array($array)) {
        return 0;
      }
    }
    
    # string
    {
      my $string = "abc";
      
      if (Fn->is_array($string)) {
        return 0;
      }
    }
    
    # Object
    {
      my $minimal = TestCase::Minimal->new;
      
      if (Fn->is_array($minimal)) {
        return 0;
      }
    }
    
    # undef
    {
      if (Fn->is_array(undef)) {
        return 0;
      }
    }

    return 1;
  }

  static method is_numeric_array : int () {

    # Numeric Array
    {
      unless (Fn->is_numeric_array(new byte[3])) {
        return 0;
      }

      unless (Fn->is_numeric_array(new double[3])) {
        return 0;
      }
    }

    # Multi Numeric Array
    {
      if (Fn->is_numeric_array(new Complex_2d[3])) {
        return 0;
      }
    }
    
    # string
    {
      my $string = "abc";
      
      if (Fn->is_numeric_array($string)) {
        return 0;
      }
    }
    
    # Object
    {
      my $minimal = TestCase::Minimal->new;
      
      if (Fn->is_numeric_array($minimal)) {
        return 0;
      }
    }

    # undef
    {
      if (Fn->is_numeric_array(undef)) {
        return 0;
      }
    }
    
    return 1;
  }

  static method is_mulnum_array : int () {

    # Numeric Array
    {
      if (Fn->is_mulnum_array(new byte[3])) {
        return 0;
      }

      if (Fn->is_mulnum_array(new double[3])) {
        return 0;
      }
    }

    # Multi Numeric Array
    {
      unless (Fn->is_mulnum_array(new Complex_2d[3])) {
        return 0;
      }
    }
    
    # string
    {
      my $string = "abc";
      
      if (Fn->is_mulnum_array($string)) {
        return 0;
      }
    }
    
    # Object
    {
      my $minimal = TestCase::Minimal->new;
      
      if (Fn->is_mulnum_array($minimal)) {
        return 0;
      }
    }

    # undef
    {
      if (Fn->is_mulnum_array(undef)) {
        return 0;
      }
    }
    
    return 1;
  }

  static method is_object_array : int () {

    # Numeric Array
    {
      if (Fn->is_object_array(new byte[3])) {
        return 0;
      }

      if (Fn->is_object_array(new double[3])) {
        return 0;
      }
    }

    # Multi Numeric Array
    {
      if (Fn->is_object_array(new Complex_2d[3])) {
        return 0;
      }
    }
    
    # string
    {
      my $string = "abc";
      
      if (Fn->is_object_array($string)) {
        return 0;
      }
    }
    
    # Object
    {
      my $minimal = TestCase::Minimal->new;
      
      if (Fn->is_object_array($minimal)) {
        return 0;
      }
    }

    # Object array
    {
      my $minimals = new TestCase::Minimal[3];
      
      unless (Fn->is_object_array($minimals)) {
        return 0;
      }
    }

    # undef
    {
      if (Fn->is_object_array(undef)) {
        return 0;
      }
    }
    
    return 1;
  }

  static method chomp : int () {
    
    # Basic
    {
      my $line = copy "abc\n";
      Fn->chomp((mutable string)$line);
      
      unless ($line eq "abc") {
        return 0;
      }
    }
    
    # Non basic cases
    {
      # no new line
      {
        my $line = copy "abc";
        Fn->chomp((mutable string)$line);
      
        unless ($line eq "abc") {
          return 0;
        }
      }
      
      # undef
      {
        my $line = (string)undef;
        Fn->chomp((mutable string)$line);
      
        unless ($line == undef) {
          return 0;
        }
      }
      
      # The length is zero
      {
        my $line = copy "";
        Fn->chomp((mutable string)$line);
        
        unless ($line eq "") {
          return 0;
        }
      }
    }
    
    return 1;
  }


  static method memcpy : int () {
    
    # Basic
    {
      # Copy numeric array
      {
        # byte
        {
          my $dist = [(byte)1, 2, 3, 4];
          my $source = [(byte)10, 11, 12, 13];
          
          Fn->memcpy($dist, 0, $source, 0, 4);
          
          my $dist_expected = [(byte)10, 11, 12, 13];
          unless (Fn->equals_array_byte($dist, $dist_expected)) {
            return 0;
          }
        }

        # double
        {
          my $dist = [(double)1, 2, 3, 4];
          my $source = [(double)10, 11, 12, 13];
          
          Fn->memcpy($dist, 0, $source, 0, 8 * 4);
          
          my $dist_expected = [(double)10, 11, 12, 13];
          unless (Fn->equals_array_double($dist, $dist_expected)) {
            return 0;
          }
        }
      }

      # Copy string
      {
        my $dist = (string)[(byte)1, 2, 3, 4];
        my $source = (string)[(byte)10, 11, 12, 13];
        
        Fn->memcpy($dist, 0, $source, 0, 4);
        
        my $dist_expected = (string)[(byte)10, 11, 12, 13];
        unless ($dist eq $dist_expected) {
          return 0;
        }
      }

      # Copy multi numeric array
      {
        my $dist = new Complex_2d[4];
        my $source = new Complex_2d[4];
        $source->[0]{re} = 1;
        $source->[0]{im} = 2;
        $source->[2]{re} = 3;
        $source->[2]{im} = 4;
        
        Fn->memcpy($dist, 0, $source, 0, 2 * 8 * 4);
        
        unless ($dist->[0]{re} == 1) {
          return 0;
        }
        unless ($dist->[0]{im} == 2) {
          return 0;
        }
        unless ($dist->[2]{re} == 3) {
          return 0;
        }
        unless ($dist->[2]{im} == 4) {
          return 0;
        }
      }

      # Copy string to bytes
      {
        my $dist = [(byte)1, 2, 3, 4];
        my $source = (string)[(byte)10, 11, 12, 13];
        
        Fn->memcpy($dist, 0, $source, 0, 4);
        
        my $dist_expected = [(byte)10, 11, 12, 13];
        unless ($dist eq $dist_expected) {
          return 0;
        }
      }
    }

    # Copy offset + length
    {
      # int
      {
        my $dist = [(int)1, 2, 3, 4];
        my $source = [(int)10, 11, 12, 13];
        
        Fn->memcpy($dist, 1 * 4, $source, 1 * 4, 2 * 4);
        
        my $dist_expected = [(int)1, 11, 12, 4];
        unless (Fn->equals_array_int($dist, $dist_expected)) {
          return 0;
        }
      }
    }
    
    # Exception
    {
      # Exception - Destnation must be defined
      {
        my $source = [(byte)1, 3, 5];
        eval { Fn->memcpy(undef, 0, $source, 0, 3); };
        unless ($@) {
          return 0;
        }
      }

      # Exception - Source must be defined
      {
        my $dest = new byte[4];
        eval { Fn->memcpy($dest, 0, undef, 0, 3); };
        unless ($@) {
          return 0;
        }
      }
      
      # Exception - Length must be more than or equals to 0
      {
        my $dest = new byte[4];
        my $source = [(byte)1, 3, 5];
        eval { Fn->memcpy($dest, 0, $source, 0, -1); };
        unless ($@) {
          return 0;
        }
      }
      
      # Exception - Destnation offset + length must be within the range of the destnation array
      {
        my $dest = new byte[4];
        my $source = [(byte)1, 3, 5];
        eval { Fn->memcpy($dest, 2, $source, 0, 3); };
        unless ($@) {
          return 0;
        }
      }

      # Exception - Source offset + length must be within the range of the source array
      {
        my $dest = new byte[4];
        my $source = [(byte)1, 3, 5];
        eval { Fn->memcpy($dest, 0, $source, 1, 3); };
        unless ($@) {
          return 0;
        }
      }
    }
    
    $@ = undef;

    
    return 1;
  }

  static method memmove : int () {
    
    # Basic
    {
      # Copy numeric array
      {
        # byte
        {
          my $dist = [(byte)1, 2, 3, 4];
          my $source = [(byte)10, 11, 12, 13];
          
          Fn->memmove($dist, 0, $source, 0, 4);
          
          my $dist_expected = [(byte)10, 11, 12, 13];
          unless (Fn->equals_array_byte($dist, $dist_expected)) {
            return 0;
          }
        }

        # double
        {
          my $dist = [(double)1, 2, 3, 4];
          my $source = [(double)10, 11, 12, 13];
          
          Fn->memmove($dist, 0, $source, 0, 8 * 4);
          
          my $dist_expected = [(double)10, 11, 12, 13];
          unless (Fn->equals_array_double($dist, $dist_expected)) {
            return 0;
          }
        }
      }

      # Copy string
      {
        my $dist = (string)[(byte)1, 2, 3, 4];
        my $source = (string)[(byte)10, 11, 12, 13];
        
        Fn->memmove($dist, 0, $source, 0, 4);
        
        my $dist_expected = (string)[(byte)10, 11, 12, 13];
        unless ($dist eq $dist_expected) {
          return 0;
        }
      }

      # Copy multi numeric array
      {
        my $dist = new Complex_2d[4];
        my $source = new Complex_2d[4];
        $source->[0]{re} = 1;
        $source->[0]{im} = 2;
        $source->[2]{re} = 3;
        $source->[2]{im} = 4;
        
        Fn->memmove($dist, 0, $source, 0, 2 * 8 * 4);
        
        unless ($dist->[0]{re} == 1) {
          return 0;
        }
        unless ($dist->[0]{im} == 2) {
          return 0;
        }
        unless ($dist->[2]{re} == 3) {
          return 0;
        }
        unless ($dist->[2]{im} == 4) {
          return 0;
        }
      }

      # Copy string to bytes
      {
        my $dist = [(byte)1, 2, 3, 4];
        my $source = (string)[(byte)10, 11, 12, 13];
        
        Fn->memmove($dist, 0, $source, 0, 4);
        
        my $dist_expected = [(byte)10, 11, 12, 13];
        unless ($dist eq $dist_expected) {
          return 0;
        }
      }
    }

    # Copy offset + length
    {
      # int
      {
        my $dist = [(int)1, 2, 3, 4];
        my $source = [(int)10, 11, 12, 13];
        
        Fn->memmove($dist, 1 * 4, $source, 1 * 4, 2 * 4);
        
        my $dist_expected = [(int)1, 11, 12, 4];
        unless (Fn->equals_array_int($dist, $dist_expected)) {
          return 0;
        }
      }
    }
    
    # Exception
    {
      # Exception - Destnation must be defined
      {
        my $source = [(byte)1, 3, 5];
        eval { Fn->memmove(undef, 0, $source, 0, 3); };
        unless ($@) {
          return 0;
        }
      }

      # Exception - Source must be defined
      {
        my $dest = new byte[4];
        eval { Fn->memmove($dest, 0, undef, 0, 3); };
        unless ($@) {
          return 0;
        }
      }
      
      # Exception - Length must be more than or equals to 0
      {
        my $dest = new byte[4];
        my $source = [(byte)1, 3, 5];
        eval { Fn->memmove($dest, 0, $source, 0, -1); };
        unless ($@) {
          return 0;
        }
      }
      
      # Exception - Destnation offset + length must be within the range of the destnation array
      {
        my $dest = new byte[4];
        my $source = [(byte)1, 3, 5];
        eval { Fn->memmove($dest, 2, $source, 0, 3); };
        unless ($@) {
          return 0;
        }
      }

      # Exception - Source offset + length must be within the range of the source array
      {
        my $dest = new byte[4];
        my $source = [(byte)1, 3, 5];
        eval { Fn->memmove($dest, 0, $source, 1, 3); };
        unless ($@) {
          return 0;
        }
      }
    }
    
    $@ = undef;

    
    return 1;
  }
}