package TestCase::Lib::SPVM::ArrayUtil {
  use SPVM::ArrayUtil(copy_array_object, equals_array_object);
  
  use SPVM::NumberUtil;
  use SPVM::Unicode (uchar);
  use TestCase::Minimal;
  use SPVM::ArrayUtil (equals_array_string);
  use TestCase::Minimal;
  use SPVM::EqualityChecker;
  use SPVM::ArrayUtil;
  use SPVM::EqualityChecker::SameObject;

  use SPVM::ArrayUtil (
    copy_array_byte,
    copy_array_short,
    copy_array_int,
    copy_array_long,
    copy_array_float,
    copy_array_double,
    copy_array_string,
    equals_array_byte,
    equals_array_short,
    equals_array_int,
    equals_array_long,
    equals_array_float,
    equals_array_double,
    dump_array_byte,
    dump_array_short,
    dump_array_int,
    dump_array_long,
    dump_array_float,
    dump_array_double,
    copy_array_range_byte,
    copy_array_range_short,
    copy_array_range_int,
    copy_array_range_long,
    copy_array_range_float,
    copy_array_range_double,
    copy_array_range_object,
    memcpy_byte,
    memcpy_short,
    memcpy_int,
    memcpy_long,
    memcpy_float,
    memcpy_double,
    memmove_byte,
    memmove_short,
    memmove_int,
    memmove_long,
    memmove_float,
    memmove_double,
    new_array_proto,
  );

  sub test_copy_array_byte : int () {
    # Copy array
    {
      my $nums = [(byte)1, 2, SPVM::NumberUtil->INT8_MIN()];
      my $nums_out = copy_array_byte($nums);

      unless ($nums->[0] == 1) {
        return 0;
      }

      unless ($nums->[1] == 2) {
        return 0;
      }

      unless ($nums->[2] == SPVM::NumberUtil->INT8_MIN()) {
        return 0;
      }

      unless (@$nums_out == 3) {
        return 0;
      }
    }
    
    # Array is undef
    {
      my $output = copy_array_byte(undef);
      unless ($output == undef) {
        return 0;
      }
    }

    return 1;
  }

  sub test_copy_array_short : int () {
    # Copy array
    {
      my $nums = [(short)1, 2, SPVM::NumberUtil->INT16_MIN()];
      my $nums_out = copy_array_short($nums);

      unless ($nums->[0] == 1) {
        return 0;
      }

      unless ($nums->[1] == 2) {
        return 0;
      }

      unless ($nums->[2] == SPVM::NumberUtil->INT16_MIN()) {
        return 0;
      }

      unless (@$nums_out == 3) {
        return 0;
      }
    }
    
    # Array is undef
    {
      my $output = copy_array_short(undef);
      unless ($output == undef) {
        return 0;
      }
    }

    return 1;
  }

  sub test_copy_array_int : int () {
    # Copy array
    {
      my $nums = [(int)1, 2, SPVM::NumberUtil->INT32_MIN()];
      my $nums_out = copy_array_int($nums);

      unless ($nums->[0] == 1) {
        return 0;
      }

      unless ($nums->[1] == 2) {
        return 0;
      }

      unless ($nums->[2] == SPVM::NumberUtil->INT32_MIN()) {
        return 0;
      }

      unless (@$nums_out == 3) {
        return 0;
      }
    }

    # Array is undef
    {
      my $output = copy_array_int(undef);
      unless ($output == undef) {
        return 0;
      }
    }

    return 1;
  }

  sub test_copy_array_long : int () {
    # Copy array
    {
      my $nums = [(long)1, 2, SPVM::NumberUtil->INT64_MIN()];
      my $nums_out = copy_array_long($nums);

      unless ($nums->[0] == 1) {
        return 0;
      }

      unless ($nums->[1] == 2) {
        return 0;
      }

      unless ($nums->[2] == SPVM::NumberUtil->INT64_MIN()) {
        return 0;
      }

      unless (@$nums_out == 3) {
        return 0;
      }
    }

    # Array is undef
    {
      my $output = copy_array_long(undef);
      unless ($output == undef) {
        return 0;
      }
    }

    return 1;
  }

  sub test_copy_array_float : int () {
    # Copy array
    {
      my $nums = [(float)0.5f, 0.25f, SPVM::NumberUtil->FLT_MIN()];
      my $nums_out = copy_array_float($nums);

      unless ($nums->[0] == 0.5) {
        return 0;
      }

      unless ($nums->[1] == 0.25) {
        return 0;
      }

      unless ($nums->[2] == SPVM::NumberUtil->FLT_MIN()) {
        return 0;
      }

      unless (@$nums_out == 3) {
        return 0;
      }
    }

    # Array is undef
    {
      my $output = copy_array_float(undef);
      unless ($output == undef) {
        return 0;
      }
    }

    return 1;
  }

  sub test_copy_array_double : int () {
    # Copy array
    {
      my $nums = [(double)0.5, 0.25, SPVM::NumberUtil->DBL_MIN()];
      my $nums_out = copy_array_double($nums);

      unless ($nums->[0] == 0.5) {
        return 0;
      }

      unless ($nums->[1] == 0.25) {
        return 0;
      }

      unless ($nums->[2] == SPVM::NumberUtil->DBL_MIN()) {
        return 0;
      }

      unless (@$nums_out == 3) {
        return 0;
      }
    }

    # Array is undef
    {
      my $output = copy_array_double(undef);
      unless ($output == undef) {
        return 0;
      }
    }

    return 1;
  }

  sub test_copy_array_string : int () {
    # Copy array
    {
      my $strings = ["abc", "def", "hij"];
      my $strings_out = copy_array_string($strings);

      unless ($strings->[0] eq $strings_out->[0]) {
        return 0;
      }
      unless ($strings->[1] eq $strings_out->[1]) {
        return 0;
      }
      unless ($strings->[2] eq $strings_out->[2]) {
        return 0;
      }

      unless ($strings->[0] != $strings_out->[0]) {
        return 0;
      }

      unless ($strings->[1] != $strings_out->[1]) {
        return 0;
      }

      unless ($strings->[2] != $strings_out->[2]) {
        return 0;
      }

      unless (@$strings_out == 3) {
        return 0;
      }
    }

    # Array is undef
    {
      my $output = copy_array_string(undef);
      unless ($output == undef) {
        return 0;
      }
    }

    return 1;
  }

  sub test_copy_array_object : int () {
    # Copy array
    {
      my $objects = [(object)SPVM::Int->new(1), SPVM::Int->new(2), SPVM::Int->new(SPVM::NumberUtil->INT32_MIN())];
      my $objects_out = copy_array_object($objects, sub : object ($self : self, $obj : object) {
        my $int_obj = (SPVM::Int)$obj;
        my $new_int_obj = SPVM::Int->new($int_obj->value);
        return $new_int_obj;
      });

      if ($objects->[0] == $objects_out->[0]) {
        return 0;
      }

      if ($objects->[1] == $objects_out->[1]) {
        return 0;
      }

      if ($objects->[2] == $objects_out->[2]) {
        return 0;
      }

      unless ((int)$objects_out->[0] == 1) {
        return 0;
      }

      unless ((int)$objects_out->[1] == 2) {
        return 0;
      }

      unless ((int)$objects_out->[2] == SPVM::NumberUtil->INT32_MIN()) {
        return 0;
      }

      unless (@$objects_out == 3) {
        return 0;
      }

      unless ($objects != $objects_out) {
        return 0;
      }
    }

    return 1;
  }

  sub test_equals_array_byte : int () {
    my $nums1 = [(byte)0, 1, SPVM::NumberUtil->INT8_MIN()];
    my $nums2 = [(byte)0, 1, SPVM::NumberUtil->INT8_MIN()];
    my $nums3 = [(byte)0, 1];
    my $nums4 = [(byte)0, 1, 2];
    {
      my $is_equals = equals_array_byte($nums1, $nums2);
      unless ($is_equals) {
        return 0;
      }
    }
    {
      my $is_equals = equals_array_byte($nums1, $nums3);
      if ($is_equals) {
        return 0;
      }
    }
    {
      my $is_equals = equals_array_byte($nums1, $nums4);
      if ($is_equals) {
        return 0;
      }
    }
    
    {
      my $is_equals = equals_array_byte(undef, undef);
      if ($is_equals) {
        return 1;
      }
    }
    
    {
      my $is_equals = equals_array_byte($nums1, undef);
      if ($is_equals) {
        return 0;
      }
    }
    
    {
      my $is_equals = equals_array_byte(undef, $nums1);
      if ($is_equals) {
        return 0;
      }
    }

    return 1;
  }

  sub test_equals_array_short : int () {
    my $nums1 = [(short)0, 1, SPVM::NumberUtil->INT16_MIN()];
    my $nums2 = [(short)0, 1, SPVM::NumberUtil->INT16_MIN()];
    my $nums3 = [(short)0, 1];
    my $nums4 = [(short)0, 1, 2];

    {
      my $is_equals = equals_array_short($nums1, $nums2);

      unless ($is_equals) {
        return 0;
      }
    }
    {
      my $is_equals = equals_array_short($nums1, $nums3);

      if ($is_equals) {
        return 0;
      }
    }
    {
      my $is_equals = equals_array_short($nums1, $nums4);
      if ($is_equals) {
        return 0;
      }
    }

    {
      my $is_equals = equals_array_short(undef, undef);
      if ($is_equals) {
        return 1;
      }
    }
    
    {
      my $is_equals = equals_array_short($nums1, undef);
      if ($is_equals) {
        return 0;
      }
    }
    
    {
      my $is_equals = equals_array_short(undef, $nums1);
      if ($is_equals) {
        return 0;
      }
    }

    return 1;
  }

  sub test_equals_array_int : int () {
    my $nums1 = [(int)0, 1, SPVM::NumberUtil->INT32_MIN()];
    my $nums2 = [(int)0, 1, SPVM::NumberUtil->INT32_MIN()];
    my $nums3 = [(int)0, 1];
    my $nums4 = [(int)0, 1, 2];

    {
      my $is_equals = equals_array_int($nums1, $nums2);
      unless ($is_equals) {
        return 0;
      }
    }
    {
      my $is_equals = equals_array_int($nums1, $nums3);
      if ($is_equals) {
        return 0;
      }
    }
    {
      my $is_equals = equals_array_int($nums1, $nums4);
      if ($is_equals) {
        return 0;
      }
    }

    {
      my $is_equals = equals_array_int(undef, undef);
      if ($is_equals) {
        return 1;
      }
    }
    
    {
      my $is_equals = equals_array_int($nums1, undef);
      if ($is_equals) {
        return 0;
      }
    }
    
    {
      my $is_equals = equals_array_int(undef, $nums1);
      if ($is_equals) {
        return 0;
      }
    }

    return 1;
  }

  sub test_equals_array_long : int () {
    my $nums1 = [(long)0, 1, SPVM::NumberUtil->INT64_MIN()];
    my $nums2 = [(long)0, 1, SPVM::NumberUtil->INT64_MIN()];
    my $nums3 = [(long)0, 1];
    my $nums4 = [(long)0, 1, 2];

    {
      my $is_equals = equals_array_long($nums1, $nums2);
      unless ($is_equals) {
        return 0;
      }
    }
    {
      my $is_equals = equals_array_long($nums1, $nums3);
      if ($is_equals) {
        return 0;
      }
    }
    {
      my $is_equals = equals_array_long($nums1, $nums4);
      if ($is_equals) {
        return 0;
      }
    }

    {
      my $is_equals = equals_array_long(undef, undef);
      if ($is_equals) {
        return 1;
      }
    }
    
    {
      my $is_equals = equals_array_long($nums1, undef);
      if ($is_equals) {
        return 0;
      }
    }
    
    {
      my $is_equals = equals_array_long(undef, $nums1);
      if ($is_equals) {
        return 0;
      }
    }

    return 1;
  }

  sub test_equals_array_float : int () {
    my $nums1 = [0.0f, 1.5f, SPVM::NumberUtil->FLT_MIN()];
    my $nums2 = [0.0f, 1.5f, SPVM::NumberUtil->FLT_MIN()];
    my $nums3 = [0.0f, 1.5f];
    my $nums4 = [(float)0.0f, 1.5f, 0.5f];

    {
      my $is_equals = equals_array_float($nums1, $nums2);
      unless ($is_equals) {
        return 0;
      }
    }
    {
      my $is_equals = equals_array_float($nums1, $nums3);
      if ($is_equals) {
        return 0;
      }
    }
    {
      my $is_equals = equals_array_float($nums1, $nums4);
      if ($is_equals) {
        return 0;
      }
    }

    {
      my $is_equals = equals_array_float(undef, undef);
      if ($is_equals) {
        return 1;
      }
    }
    
    {
      my $is_equals = equals_array_float($nums1, undef);
      if ($is_equals) {
        return 0;
      }
    }
    
    {
      my $is_equals = equals_array_float(undef, $nums1);
      if ($is_equals) {
        return 0;
      }
    }

    return 1;
  }

  sub test_equals_array_double : int () {
    my $nums1 = [0.0, 1.5, SPVM::NumberUtil->DBL_MIN()];
    my $nums2 = [0.0, 1.5, SPVM::NumberUtil->DBL_MIN()];
    my $nums3 = [0.0, 1.5];
    my $nums4 = [(double)0.0, 1.5, 0.5];

    {
      my $is_equals = equals_array_double($nums1, $nums2);
      unless ($is_equals) {
        return 0;
      }
    }
    {
      my $is_equals = equals_array_double($nums1, $nums3);
      if ($is_equals) {
        return 0;
      }
    }
    {
      my $is_equals = equals_array_double($nums1, $nums4);
      if ($is_equals) {
        return 0;
      }
    }

    {
      my $is_equals = equals_array_double(undef, undef);
      if ($is_equals) {
        return 1;
      }
    }
    
    {
      my $is_equals = equals_array_double($nums1, undef);
      if ($is_equals) {
        return 0;
      }
    }
    
    {
      my $is_equals = equals_array_double(undef, $nums1);
      if ($is_equals) {
        return 0;
      }
    }

    return 1;
  }

  sub test_equals_array_string : int () {
    my $strings1 = ["abc", "def", "ghi"];
    my $strings2 = ["abc", "def", "ghi"];
    my $strings3 = ["abc", "def"];
    my $strings4 = ["abc", "def", "xxx"];

    {
      my $is_equals = equals_array_string($strings1, $strings2);
      unless ($is_equals) {
        return 0;
      }
    }
    {
      my $is_equals = equals_array_string($strings1, $strings3);
      if ($is_equals) {
        return 0;
      }
    }
    {
      my $is_equals = equals_array_string($strings1, $strings4);
      if ($is_equals) {
        return 0;
      }
    }

    {
      my $is_equals = equals_array_string(undef, undef);
      if ($is_equals) {
        return 1;
      }
    }
    
    {
      my $is_equals = equals_array_string($strings1, undef);
      if ($is_equals) {
        return 0;
      }
    }
    
    {
      my $is_equals = equals_array_string(undef, $strings1);
      if ($is_equals) {
        return 0;
      }
    }

    return 1;
  }
  sub test_equals_array_object : int () {
    my $minimal1 = TestCase::Minimal->new;
    my $minimal2 = TestCase::Minimal->new;
    my $minimal3 = TestCase::Minimal->new;
    my $minimal4 = TestCase::Minimal->new;
    my $nums1 = [$minimal1, $minimal2, $minimal3];
    my $nums2 = [$minimal1, $minimal2, $minimal3];
    my $nums3 = [$minimal1, $minimal2];
    my $nums4 = [$minimal1, $minimal2, $minimal4];
    my $nums5 = [(object)$minimal1, $minimal2, $minimal3];

    my $equality_checker = sub : int ($self : self, $object1 : object, $object2 : object) {
      my $minimal1 = (TestCase::Minimal)$object1;
      my $minimal2 = (TestCase::Minimal)$object2;

      if ($minimal1 == $minimal2) {
        return 1;
      }
      else {
        return 0;
      }
    };

    {
      my $is_equals = equals_array_object($nums1, $nums2, $equality_checker);
      unless ($is_equals) {
        return 0;
      }
    }
    {
      my $is_equals = equals_array_object($nums1, $nums3, $equality_checker);
      if ($is_equals) {
        return 0;
      }
    }
    {
      my $is_equals = equals_array_object($nums1, $nums4, $equality_checker);
      if ($is_equals) {
        return 0;
      }
    }
    {
      my $is_equals = equals_array_object($nums1, $nums5, $equality_checker);
      unless ($is_equals) {
        return 0;
      }
    }

    return 1;
  }

  sub test_memcpy_byte : int () {
    
    # Copy
    {
      my $dest = new byte[4];
      my $source = [(byte)1, 3, 5];
      memcpy_byte($dest, 0, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_byte($dest, [(byte)1, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with offset
    {
      my $dest = new byte[4];
      my $source = [(byte)1, 3, 5];
      memcpy_byte($dest, 1, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_byte($dest, [(byte)0, 1, 3, 5])) {
        return 0;
      }
    }

    # Copy with offset and length
    {
      my $dest = new byte[4];
      my $source = [(byte)1, 3, 5, 9];
      memcpy_byte($dest, 1, $source, 1, 2);
      unless (SPVM::ArrayUtil->equals_array_byte($dest, [(byte)0, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with 0 length
    {
      my $dest = new byte[4];
      my $source = [(byte)1, 3, 5];
      memcpy_byte($dest, 0, $source, 0, 0);
      unless (SPVM::ArrayUtil->equals_array_byte($dest, [(byte)0, 0, 0, 0])) {
        return 0;
      }
    }

    # Exception - Destnation must be defined
    {
      my $source = [(byte)1, 3, 5];
      eval { memcpy_byte(undef, 0, $source, 0, 3); };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Source must be defined
    {
      my $dest = new byte[4];
      eval { memcpy_byte($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 { memcpy_byte($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 { memcpy_byte($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 { memcpy_byte($dest, 0, $source, 1, 3); };
      unless ($@) {
        return 0;
      }
    }
    
    $@ = undef;

    return 1;
  }


  sub test_memcpy_short : int () {
    
    # Copy
    {
      my $dest = new short[4];
      my $source = [(short)1, 3, 5];
      memcpy_short($dest, 0, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_short($dest, [(short)1, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with offset
    {
      my $dest = new short[4];
      my $source = [(short)1, 3, 5];
      memcpy_short($dest, 1, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_short($dest, [(short)0, 1, 3, 5])) {
        return 0;
      }
    }

    # Copy with offset and length
    {
      my $dest = new short[4];
      my $source = [(short)1, 3, 5, 9];
      memcpy_short($dest, 1, $source, 1, 2);
      unless (SPVM::ArrayUtil->equals_array_short($dest, [(short)0, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with 0 length
    {
      my $dest = new short[4];
      my $source = [(short)1, 3, 5];
      memcpy_short($dest, 0, $source, 0, 0);
      unless (SPVM::ArrayUtil->equals_array_short($dest, [(short)0, 0, 0, 0])) {
        return 0;
      }
    }

    # Exception - Destnation must be defined
    {
      my $source = [(short)1, 3, 5];
      eval { memcpy_short(undef, 0, $source, 0, 3); };
      unless ($@) {
        return 0;
      }
    }

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

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

    return 1;
  }

  sub test_memcpy_int : int () {
    
    # Copy
    {
      my $dest = new int[4];
      my $source = [(int)1, 3, 5];
      memcpy_int($dest, 0, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_int($dest, [(int)1, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with offset
    {
      my $dest = new int[4];
      my $source = [(int)1, 3, 5];
      memcpy_int($dest, 1, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_int($dest, [(int)0, 1, 3, 5])) {
        return 0;
      }
    }

    # Copy with offset and length
    {
      my $dest = new int[4];
      my $source = [(int)1, 3, 5, 9];
      memcpy_int($dest, 1, $source, 1, 2);
      unless (SPVM::ArrayUtil->equals_array_int($dest, [(int)0, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with 0 length
    {
      my $dest = new int[4];
      my $source = [(int)1, 3, 5];
      memcpy_int($dest, 0, $source, 0, 0);
      unless (SPVM::ArrayUtil->equals_array_int($dest, [(int)0, 0, 0, 0])) {
        return 0;
      }
    }

    # Exception - Destnation must be defined
    {
      my $source = [(int)1, 3, 5];
      eval { memcpy_int(undef, 0, $source, 0, 3); };
      unless ($@) {
        return 0;
      }
    }

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

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

    return 1;
  }

  sub test_memcpy_long : int () {
    
    # Copy
    {
      my $dest = new long[4];
      my $source = [(long)1, 3, 5];
      memcpy_long($dest, 0, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_long($dest, [(long)1, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with offset
    {
      my $dest = new long[4];
      my $source = [(long)1, 3, 5];
      memcpy_long($dest, 1, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_long($dest, [(long)0, 1, 3, 5])) {
        return 0;
      }
    }

    # Copy with offset and length
    {
      my $dest = new long[4];
      my $source = [(long)1, 3, 5, 9];
      memcpy_long($dest, 1, $source, 1, 2);
      unless (SPVM::ArrayUtil->equals_array_long($dest, [(long)0, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with 0 length
    {
      my $dest = new long[4];
      my $source = [(long)1, 3, 5];
      memcpy_long($dest, 0, $source, 0, 0);
      unless (SPVM::ArrayUtil->equals_array_long($dest, [(long)0, 0, 0, 0])) {
        return 0;
      }
    }

    # Exception - Destnation must be defined
    {
      my $source = [(long)1, 3, 5];
      eval { memcpy_long(undef, 0, $source, 0, 3); };
      unless ($@) {
        return 0;
      }
    }

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

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

    return 1;
  }

  sub test_memcpy_float : int () {
    
    # Copy
    {
      my $dest = new float[4];
      my $source = [(float)1, 3, 5];
      memcpy_float($dest, 0, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_float($dest, [(float)1, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with offset
    {
      my $dest = new float[4];
      my $source = [(float)1, 3, 5];
      memcpy_float($dest, 1, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_float($dest, [(float)0, 1, 3, 5])) {
        return 0;
      }
    }

    # Copy with offset and length
    {
      my $dest = new float[4];
      my $source = [(float)1, 3, 5, 9];
      memcpy_float($dest, 1, $source, 1, 2);
      unless (SPVM::ArrayUtil->equals_array_float($dest, [(float)0, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with 0 length
    {
      my $dest = new float[4];
      my $source = [(float)1, 3, 5];
      memcpy_float($dest, 0, $source, 0, 0);
      unless (SPVM::ArrayUtil->equals_array_float($dest, [(float)0, 0, 0, 0])) {
        return 0;
      }
    }

    # Exception - Destnation must be defined
    {
      my $source = [(float)1, 3, 5];
      eval { memcpy_float(undef, 0, $source, 0, 3); };
      unless ($@) {
        return 0;
      }
    }

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

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

    return 1;
  }

  sub test_memcpy_double : int () {
    
    # Copy
    {
      my $dest = new double[4];
      my $source = [(double)1, 3, 5];
      memcpy_double($dest, 0, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_double($dest, [(double)1, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with offset
    {
      my $dest = new double[4];
      my $source = [(double)1, 3, 5];
      memcpy_double($dest, 1, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_double($dest, [(double)0, 1, 3, 5])) {
        return 0;
      }
    }

    # Copy with offset and length
    {
      my $dest = new double[4];
      my $source = [(double)1, 3, 5, 9];
      memcpy_double($dest, 1, $source, 1, 2);
      unless (SPVM::ArrayUtil->equals_array_double($dest, [(double)0, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with 0 length
    {
      my $dest = new double[4];
      my $source = [(double)1, 3, 5];
      memcpy_double($dest, 0, $source, 0, 0);
      unless (SPVM::ArrayUtil->equals_array_double($dest, [(double)0, 0, 0, 0])) {
        return 0;
      }
    }

    # Exception - Destnation must be defined
    {
      my $source = [(double)1, 3, 5];
      eval { memcpy_double(undef, 0, $source, 0, 3); };
      unless ($@) {
        return 0;
      }
    }

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

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

    return 1;
  }

  sub test_memmove_byte : int () {
    
    # Copy
    {
      my $dest = new byte[4];
      my $source = [(byte)1, 3, 5];
      memmove_byte($dest, 0, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_byte($dest, [(byte)1, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with offset
    {
      my $dest = new byte[4];
      my $source = [(byte)1, 3, 5];
      memmove_byte($dest, 1, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_byte($dest, [(byte)0, 1, 3, 5])) {
        return 0;
      }
    }

    # Copy with offset and length
    {
      my $dest = new byte[4];
      my $source = [(byte)1, 3, 5, 9];
      memmove_byte($dest, 1, $source, 1, 2);
      unless (SPVM::ArrayUtil->equals_array_byte($dest, [(byte)0, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with 0 length
    {
      my $dest = new byte[4];
      my $source = [(byte)1, 3, 5];
      memmove_byte($dest, 0, $source, 0, 0);
      unless (SPVM::ArrayUtil->equals_array_byte($dest, [(byte)0, 0, 0, 0])) {
        return 0;
      }
    }
    
    # Copy overwrap
    {
      my $dest = [(byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
      memmove_byte($dest, 0, $dest, 1, 9);
      unless (SPVM::ArrayUtil->equals_array_byte($dest, [(byte)2, 3, 4, 5, 6, 7, 8, 9, 10, 10])) {
        return 0;
      }
    }

    # Exception - Destnation must be defined
    {
      my $source = [(byte)1, 3, 5];
      eval { memmove_byte(undef, 0, $source, 0, 3); };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Source must be defined
    {
      my $dest = new byte[4];
      eval { memmove_byte($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 { memmove_byte($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 { memmove_byte($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 { memmove_byte($dest, 0, $source, 1, 3); };
      unless ($@) {
        return 0;
      }
    }
    
    $@ = undef;

    return 1;
  }

  sub test_memmove_short : int () {
    
    # Copy
    {
      my $dest = new short[4];
      my $source = [(short)1, 3, 5];
      memmove_short($dest, 0, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_short($dest, [(short)1, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with offset
    {
      my $dest = new short[4];
      my $source = [(short)1, 3, 5];
      memmove_short($dest, 1, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_short($dest, [(short)0, 1, 3, 5])) {
        return 0;
      }
    }

    # Copy with offset and length
    {
      my $dest = new short[4];
      my $source = [(short)1, 3, 5, 9];
      memmove_short($dest, 1, $source, 1, 2);
      unless (SPVM::ArrayUtil->equals_array_short($dest, [(short)0, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with 0 length
    {
      my $dest = new short[4];
      my $source = [(short)1, 3, 5];
      memmove_short($dest, 0, $source, 0, 0);
      unless (SPVM::ArrayUtil->equals_array_short($dest, [(short)0, 0, 0, 0])) {
        return 0;
      }
    }
    
    # Copy overwrap
    {
      my $dest = [(short)1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
      memmove_short($dest, 0, $dest, 1, 9);
      unless (SPVM::ArrayUtil->equals_array_short($dest, [(short)2, 3, 4, 5, 6, 7, 8, 9, 10, 10])) {
        return 0;
      }
    }

    # Exception - Destnation must be defined
    {
      my $source = [(short)1, 3, 5];
      eval { memmove_short(undef, 0, $source, 0, 3); };
      unless ($@) {
        return 0;
      }
    }

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

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

    return 1;
  }

  sub test_memmove_int : int () {
    
    # Copy
    {
      my $dest = new int[4];
      my $source = [(int)1, 3, 5];
      memmove_int($dest, 0, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_int($dest, [(int)1, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with offset
    {
      my $dest = new int[4];
      my $source = [(int)1, 3, 5];
      memmove_int($dest, 1, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_int($dest, [(int)0, 1, 3, 5])) {
        return 0;
      }
    }

    # Copy with offset and length
    {
      my $dest = new int[4];
      my $source = [(int)1, 3, 5, 9];
      memmove_int($dest, 1, $source, 1, 2);
      unless (SPVM::ArrayUtil->equals_array_int($dest, [(int)0, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with 0 length
    {
      my $dest = new int[4];
      my $source = [(int)1, 3, 5];
      memmove_int($dest, 0, $source, 0, 0);
      unless (SPVM::ArrayUtil->equals_array_int($dest, [(int)0, 0, 0, 0])) {
        return 0;
      }
    }
    
    # Copy overwrap
    {
      my $dest = [(int)1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
      memmove_int($dest, 0, $dest, 1, 9);
      unless (SPVM::ArrayUtil->equals_array_int($dest, [(int)2, 3, 4, 5, 6, 7, 8, 9, 10, 10])) {
        return 0;
      }
    }

    # Exception - Destnation must be defined
    {
      my $source = [(int)1, 3, 5];
      eval { memmove_int(undef, 0, $source, 0, 3); };
      unless ($@) {
        return 0;
      }
    }

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

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

    return 1;
  }

  sub test_memmove_long : int () {
    
    # Copy
    {
      my $dest = new long[4];
      my $source = [(long)1, 3, 5];
      memmove_long($dest, 0, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_long($dest, [(long)1, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with offset
    {
      my $dest = new long[4];
      my $source = [(long)1, 3, 5];
      memmove_long($dest, 1, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_long($dest, [(long)0, 1, 3, 5])) {
        return 0;
      }
    }

    # Copy with offset and length
    {
      my $dest = new long[4];
      my $source = [(long)1, 3, 5, 9];
      memmove_long($dest, 1, $source, 1, 2);
      unless (SPVM::ArrayUtil->equals_array_long($dest, [(long)0, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with 0 length
    {
      my $dest = new long[4];
      my $source = [(long)1, 3, 5];
      memmove_long($dest, 0, $source, 0, 0);
      unless (SPVM::ArrayUtil->equals_array_long($dest, [(long)0, 0, 0, 0])) {
        return 0;
      }
    }
    
    # Copy overwrap
    {
      my $dest = [(long)1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
      memmove_long($dest, 0, $dest, 1, 9);
      unless (SPVM::ArrayUtil->equals_array_long($dest, [(long)2, 3, 4, 5, 6, 7, 8, 9, 10, 10])) {
        return 0;
      }
    }

    # Exception - Destnation must be defined
    {
      my $source = [(long)1, 3, 5];
      eval { memmove_long(undef, 0, $source, 0, 3); };
      unless ($@) {
        return 0;
      }
    }

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

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

    return 1;
  }

  sub test_memmove_float : int () {
    
    # Copy
    {
      my $dest = new float[4];
      my $source = [(float)1, 3, 5];
      memmove_float($dest, 0, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_float($dest, [(float)1, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with offset
    {
      my $dest = new float[4];
      my $source = [(float)1, 3, 5];
      memmove_float($dest, 1, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_float($dest, [(float)0, 1, 3, 5])) {
        return 0;
      }
    }

    # Copy with offset and length
    {
      my $dest = new float[4];
      my $source = [(float)1, 3, 5, 9];
      memmove_float($dest, 1, $source, 1, 2);
      unless (SPVM::ArrayUtil->equals_array_float($dest, [(float)0, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with 0 length
    {
      my $dest = new float[4];
      my $source = [(float)1, 3, 5];
      memmove_float($dest, 0, $source, 0, 0);
      unless (SPVM::ArrayUtil->equals_array_float($dest, [(float)0, 0, 0, 0])) {
        return 0;
      }
    }
    
    # Copy overwrap
    {
      my $dest = [(float)1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
      memmove_float($dest, 0, $dest, 1, 9);
      unless (SPVM::ArrayUtil->equals_array_float($dest, [(float)2, 3, 4, 5, 6, 7, 8, 9, 10, 10])) {
        return 0;
      }
    }

    # Exception - Destnation must be defined
    {
      my $source = [(float)1, 3, 5];
      eval { memmove_float(undef, 0, $source, 0, 3); };
      unless ($@) {
        return 0;
      }
    }

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

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

    return 1;
  }

  sub test_memmove_double : int () {
    
    # Copy
    {
      my $dest = new double[4];
      my $source = [(double)1, 3, 5];
      memmove_double($dest, 0, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_double($dest, [(double)1, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with offset
    {
      my $dest = new double[4];
      my $source = [(double)1, 3, 5];
      memmove_double($dest, 1, $source, 0, 3);
      unless (SPVM::ArrayUtil->equals_array_double($dest, [(double)0, 1, 3, 5])) {
        return 0;
      }
    }

    # Copy with offset and length
    {
      my $dest = new double[4];
      my $source = [(double)1, 3, 5, 9];
      memmove_double($dest, 1, $source, 1, 2);
      unless (SPVM::ArrayUtil->equals_array_double($dest, [(double)0, 3, 5, 0])) {
        return 0;
      }
    }

    # Copy with 0 length
    {
      my $dest = new double[4];
      my $source = [(double)1, 3, 5];
      memmove_double($dest, 0, $source, 0, 0);
      unless (SPVM::ArrayUtil->equals_array_double($dest, [(double)0, 0, 0, 0])) {
        return 0;
      }
    }
    
    # Copy overwrap
    {
      my $dest = [(double)1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
      memmove_double($dest, 0, $dest, 1, 9);
      unless (SPVM::ArrayUtil->equals_array_double($dest, [(double)2, 3, 4, 5, 6, 7, 8, 9, 10, 10])) {
        return 0;
      }
    }

    # Exception - Destnation must be defined
    {
      my $source = [(double)1, 3, 5];
      eval { memmove_double(undef, 0, $source, 0, 3); };
      unless ($@) {
        return 0;
      }
    }

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

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

    return 1;
  }

  sub test_dump_array_byte : int () {
    # Dump array
    {
      my $nums = [(byte)1, 2, SPVM::NumberUtil->INT8_MIN()];

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

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

    return 1;
  }

  sub test_dump_array_short : int () {
    # Dump array
    {
      my $nums = [(short)1, 2, SPVM::NumberUtil->INT16_MIN()];

      my $dump = dump_array_short($nums);

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

    return 1;
  }

  sub test_dump_array_int : int () {
    # Dump array
    {
      my $nums = [(int)1, 2, SPVM::NumberUtil->INT32_MIN()];

      my $dump = dump_array_int($nums);

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

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


    return 1;
  }

  sub test_dump_array_long : int () {
    # Dump array
    {
      my $nums = [(long)1, 2, SPVM::NumberUtil->INT64_MIN()];

      my $dump = dump_array_long($nums);

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

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


    return 1;
  }

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

      my $dump = dump_array_float($nums);

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

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

    return 1;
  }

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

      my $dump = dump_array_double($nums);

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

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

    return 1;
  }

  sub test_dump_unsigned_array_byte : int () {
    # Dump array
    {
      my $nums = [(byte)1, 2, -1, SPVM::NumberUtil->UINT8_MAX];
      
      my $dump = SPVM::ArrayUtil->dump_array_unsigned_byte($nums);
      
      unless ($dump eq "[\n  1,\n  2,\n  255,\n  255\n]") {
        return 0;
      }
    }

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

    return 1;
  }

  sub test_dump_unsigned_array_short : int () {
    # Dump array
    {
      my $nums = [(short)1, 2, -1, SPVM::NumberUtil->UINT16_MAX];
      
      my $dump = SPVM::ArrayUtil->dump_array_unsigned_short($nums);
      
      unless ($dump eq "[\n  1,\n  2,\n  65535,\n  65535\n]") {
        return 0;
      }
    }

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

    return 1;
  }

  sub test_dump_unsigned_array_int : int () {
    # Dump array
    {
      my $nums = [(int)1, 2, -1, SPVM::NumberUtil->UINT32_MAX];
      
      my $dump = SPVM::ArrayUtil->dump_array_unsigned_int($nums);
      
      unless ($dump eq "[\n  1,\n  2,\n  4294967295,\n  4294967295\n]") {
        return 0;
      }
    }

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

    return 1;
  }

  sub test_dump_unsigned_array_long : long () {
    # Dump array
    {
      my $nums = [(long)1, 2, -1, SPVM::NumberUtil->UINT64_MAX];
      
      my $dump = SPVM::ArrayUtil->dump_array_unsigned_long($nums);
      
      unless ($dump eq "[\n  1,\n  2,\n  18446744073709551615,\n  18446744073709551615\n]") {
        return 0;
      }
    }

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

    return 1;
  }

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

      my $dump = SPVM::ArrayUtil->dump_array_string($strings);

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

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

    return 1;
  }

  sub test_dump_array_object : int () {
    
    {
      my $minimals = [
        TestCase::Minimal->newp(1, 2),
        TestCase::Minimal->newp(3, 4),
        TestCase::Minimal->newp(5, 6)
      ];

      my $dump = SPVM::ArrayUtil->dump_array_object($minimals, sub : string ($self : self, $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 = SPVM::ArrayUtil->dump_array_object(undef, undef);
      
      unless ($dump == undef) {
        return 0;
      }
    }

    return 1;
  }


  sub test_new_array_proto : int () {
    my $minimals = new TestCase::Minimal[1];

    my $new_array_object = new_array_proto($minimals, 2);
    unless ($new_array_object isa TestCase::Minimal[]) {
      return 0;
    }
    my $new_minimals = (TestCase::Minimal[])$new_array_object;
    unless (@$new_minimals == 2) {
      return 0;
    }

    return 1;
  }
  sub test_copy_array_range_byte : int () {
    {
      my $nums = [(byte)5, -7, 9, SPVM::NumberUtil->INT8_MIN(), 127, 15, 19];
      my $range = copy_array_range_byte($nums, 0, 7);
      unless (equals_array_byte($range, [(byte)5, -7, 9, SPVM::NumberUtil->INT8_MIN(), 127, 15, 19])) {
        return 0;
      }
    }

    {
      my $nums = [(byte)5, -7, 9, SPVM::NumberUtil->INT8_MIN(), 127, 15, 19];
      my $range = copy_array_range_byte($nums, 1, 3);
      unless (equals_array_byte($range, [(byte)-7, 9, SPVM::NumberUtil->INT8_MIN()])) {
        return 0;
      }
    }
    
    # Exception - The argument array must be defined
    {
      eval { copy_array_range_byte(undef, 0, 7); };
      unless ($@) {
        return 0;
      }
    }
    
    # Exception - Offset must be in the array range
    {
      {
	      eval { copy_array_range_byte([(byte)5, -7, 9], -1, 1); };
	      unless ($@) {
	        return 0;
	      }
	    }
      {
	      eval { copy_array_range_byte([(byte)5, -7, 9], 3, 1); };
	      unless ($@) {
	        return 0;
	      }
	    }
    }

    # Exception - Offset + length must be in the array range
    {
      {
	      eval { copy_array_range_byte([(byte)5, -7, 9], 1, 3); };
	      unless ($@) {
	        return 0;
	      }
	    }
    }

    return 1;
  }
  sub test_copy_array_range_short : int () {
    {
      my $nums = [(short)5, -7, 9, SPVM::NumberUtil->INT16_MIN(), 127, 15, 19];
      my $range = copy_array_range_short($nums, 0, 7);
      unless (equals_array_short($range, [(short)5, -7, 9, SPVM::NumberUtil->INT16_MIN(), 127, 15, 19])) {
        return 0;
      }
    }
    {
      my $nums = [(short)5, -7, 9, SPVM::NumberUtil->INT16_MIN(), 127, 15, 19];
      my $range = copy_array_range_short($nums, 1, 3);
      unless (equals_array_short($range, [(short)-7, 9, SPVM::NumberUtil->INT16_MIN()])) {
        return 0;
      }
    }

    # Exception - The argument array must be defined
    {
      eval { copy_array_range_short(undef, 0, 7); };
      unless ($@) {
        return 0;
      }
    }
    
    # Exception - Offset must be in the array range
    {
      {
	      eval { copy_array_range_short([(short)5, -7, 9], -1, 1); };
	      unless ($@) {
	        return 0;
	      }
	    }
      {
	      eval { copy_array_range_short([(short)5, -7, 9], 3, 1); };
	      unless ($@) {
	        return 0;
	      }
	    }
    }

    # Exception - Offset + length must be in the array range
    {
      {
	      eval { copy_array_range_short([(short)5, -7, 9], 1, 3); };
	      unless ($@) {
	        return 0;
	      }
	    }
    }

    return 1;
  }
  sub test_copy_array_range_int : int () {
    {
      my $nums = [(int)5, -7, 9, SPVM::NumberUtil->INT32_MIN(), 127, 15, 19];
      my $range = copy_array_range_int($nums, 0, 7);
      unless (equals_array_int($range, [(int)5, -7, 9, SPVM::NumberUtil->INT32_MIN(), 127, 15, 19])) {
        return 0;
      }
    }
    {
      my $nums = [(int)5, -7, 9, SPVM::NumberUtil->INT32_MIN(), 127, 15, 19];
      my $range = copy_array_range_int($nums, 1, 3);
      unless (equals_array_int($range, [(int)-7, 9, SPVM::NumberUtil->INT32_MIN()])) {
        return 0;
      }
    }

    # Exception - The argument array must be defined
    {
      eval { copy_array_range_int(undef, 0, 7); };
      unless ($@) {
        return 0;
      }
    }
    
    # Exception - Offset must be in the array range
    {
      {
	      eval { copy_array_range_int([(int)5, -7, 9], -1, 1); };
	      unless ($@) {
	        return 0;
	      }
	    }
      {
	      eval { copy_array_range_int([(int)5, -7, 9], 3, 1); };
	      unless ($@) {
	        return 0;
	      }
	    }
    }

    # Exception - Offset + length must be in the array range
    {
      {
	      eval { copy_array_range_int([(int)5, -7, 9], 1, 3); };
	      unless ($@) {
	        return 0;
	      }
	    }
    }

    return 1;
  }
  sub test_copy_array_range_long : int () {
    {
      my $nums = [(long)5, -7, 9, SPVM::NumberUtil->INT64_MIN(), 127, 15, 19];
      my $range = copy_array_range_long($nums, 0, 7);
      unless (equals_array_long($range, [(long)5, -7, 9, SPVM::NumberUtil->INT64_MIN(), 127, 15, 19])) {
        return 0;
      }
    }
    {
      my $nums = [(long)5, -7, 9, SPVM::NumberUtil->INT64_MIN(), 127, 15, 19];
      my $range = copy_array_range_long($nums, 1, 3);
      unless (equals_array_long($range, [(long)-7, 9, SPVM::NumberUtil->INT64_MIN()])) {
        return 0;
      }
    }

    # Exception - The argument array must be defined
    {
      eval { copy_array_range_long(undef, 0, 7); };
      unless ($@) {
        return 0;
      }
    }
    
    # Exception - Offset must be in the array range
    {
      {
	      eval { copy_array_range_long([(long)5, -7, 9], -1, 1); };
	      unless ($@) {
	        return 0;
	      }
	    }
      {
	      eval { copy_array_range_long([(long)5, -7, 9], 3, 1); };
	      unless ($@) {
	        return 0;
	      }
	    }
    }

    # Exception - Offset + length must be in the array range
    {
      {
	      eval { copy_array_range_long([(long)5, -7, 9], 1, 3); };
	      unless ($@) {
	        return 0;
	      }
	    }
    }

    return 1;
  }
  sub test_copy_array_range_float : int () {
    {
      my $nums = [(float)5, -7, 9, SPVM::NumberUtil->FLT_MIN(), 127, 15, 19];
      my $range = copy_array_range_float($nums, 0, 7);
      unless (equals_array_float($range, [(float)5, -7, 9, SPVM::NumberUtil->FLT_MIN(), 127, 15, 19])) {
        return 0;
      }
    }
    {
      my $nums = [(float)5, -7, 9, SPVM::NumberUtil->FLT_MIN(), 127, 15, 19];
      my $range = copy_array_range_float($nums, 1, 3);
      unless (equals_array_float($range, [(float)-7, 9, SPVM::NumberUtil->FLT_MIN()])) {
        return 0;
      }
    }

    # Exception - The argument array must be defined
    {
      eval { copy_array_range_float(undef, 0, 7); };
      unless ($@) {
        return 0;
      }
    }
    
    # Exception - Offset must be in the array range
    {
      {
	      eval { copy_array_range_float([(float)5, -7, 9], -1, 1); };
	      unless ($@) {
	        return 0;
	      }
	    }
      {
	      eval { copy_array_range_float([(float)5, -7, 9], 3, 1); };
	      unless ($@) {
	        return 0;
	      }
	    }
    }

    # Exception - Offset + length must be in the array range
    {
      {
	      eval { copy_array_range_float([(float)5, -7, 9], 1, 3); };
	      unless ($@) {
	        return 0;
	      }
	    }
    }

    return 1;
  }
  
  sub test_copy_array_range_double : int () {
    {
      my $nums = [(double)5, -7, 9, SPVM::NumberUtil->DBL_MIN(), 127, 15, 19];
      my $range = copy_array_range_double($nums, 0, 7);
      unless (equals_array_double($range, [(double)5, -7, 9, SPVM::NumberUtil->DBL_MIN(), 127, 15, 19])) {
        return 0;
      }
    }
    {
      my $nums = [(double)5, -7, 9, SPVM::NumberUtil->DBL_MIN(), 127, 15, 19];
      my $range = copy_array_range_double($nums, 1, 3);
      unless (equals_array_double($range, [(double)-7, 9, SPVM::NumberUtil->DBL_MIN()])) {
        return 0;
      }
    }

    # Exception - The argument array must be defined
    {
      eval { copy_array_range_double(undef, 0, 7); };
      unless ($@) {
        return 0;
      }
    }
    
    # Exception - Offset must be in the array range
    {
      {
	      eval { copy_array_range_double([(double)5, -7, 9], -1, 1); };
	      unless ($@) {
	        return 0;
	      }
	    }
      {
	      eval { copy_array_range_double([(double)5, -7, 9], 3, 1); };
	      unless ($@) {
	        return 0;
	      }
	    }
    }

    # Exception - Offset + length must be in the array range
    {
      {
	      eval { copy_array_range_double([(double)5, -7, 9], 1, 3); };
	      unless ($@) {
	        return 0;
	      }
	    }
    }

    return 1;
  }

  sub test_copy_array_range_string : int () {
    {
      my $strings = ["a", "b", "c", "d", "e", "f", "g"];
      my $range = SPVM::ArrayUtil->copy_array_range_string($strings, 0, 7);
      unless (equals_array_string($range, ["a", "b", "c", "d", "e", "f", "g"])) {
        return 0;
      }
    }
    {
      my $strings = ["a", "b", "c", "d", "e", "f", "g"];
      my $range = SPVM::ArrayUtil->copy_array_range_string($strings, 1, 3);
      unless (equals_array_string($range, ["b", "c", "d"])) {
        return 0;
      }
    }

    # Exception - The argument array must be defined
    {
      eval { SPVM::ArrayUtil->copy_array_range_string(undef, 0, 7); };
      unless ($@) {
        return 0;
      }
    }
    
    # Exception - Offset must be in the array range
    {
      {
	      eval { SPVM::ArrayUtil->copy_array_range_string([(string)5, -7, 9], -1, 1); };
	      unless ($@) {
	        return 0;
	      }
	    }
      {
	      eval { SPVM::ArrayUtil->copy_array_range_string([(string)5, -7, 9], 3, 1); };
	      unless ($@) {
	        return 0;
	      }
	    }
    }

    # Exception - Offset + length must be in the array range
    {
      {
	      eval { SPVM::ArrayUtil->copy_array_range_string([(string)5, -7, 9], 1, 3); };
	      unless ($@) {
	        return 0;
	      }
	    }
    }

    return 1;
  }

  sub test_copy_array_range_object : int () {

    {
      my $minimal1 = TestCase::Minimal->new;
      my $minimal2 = TestCase::Minimal->new;
      my $minimal3 = TestCase::Minimal->new;
      my $minimal4 = TestCase::Minimal->new;

      my $elems = [$minimal1, $minimal2, $minimal3, $minimal4];
      my $range = (TestCase::Minimal[])copy_array_range_object($elems, 0, 4);
      unless (SPVM::ArrayUtil->equals_array_object($range, [$minimal1, $minimal2, $minimal3, $minimal4], SPVM::EqualityChecker::SameObject->new)) {
        return 0;
      }
    }
    {
      my $minimal1 = TestCase::Minimal->new;
      my $minimal2 = TestCase::Minimal->new;
      my $minimal3 = TestCase::Minimal->new;
      my $minimal4 = TestCase::Minimal->new;

      my $elems = [$minimal1, $minimal2, $minimal3, $minimal4];
      my $range = (TestCase::Minimal[])copy_array_range_object($elems, 1, 2);
      unless (SPVM::ArrayUtil->equals_array_object($range, [$minimal2, $minimal3], SPVM::EqualityChecker::SameObject->new)) {
        return 0;
      }
    }

    # Exception - The argument array must be defined
    {
      eval { copy_array_range_object(undef, 0, 7); };
      unless ($@) {
        return 0;
      }
    }
    
    # Exception - Offset must be in the array range
    {
      my $minimal1 = TestCase::Minimal->new;
      my $minimal2 = TestCase::Minimal->new;
      my $minimal3 = TestCase::Minimal->new;
      {
	      eval { copy_array_range_object([$minimal1, $minimal2, $minimal3], -1, 1); };
	      unless ($@) {
	        return 0;
	      }
	    }
      {
	      eval { copy_array_range_object([$minimal1, $minimal2, $minimal3], 3, 1); };
	      unless ($@) {
	        return 0;
	      }
	    }
    }

    # Exception - Offset + length must be in the array range
    {
      {
	      my $minimal1 = TestCase::Minimal->new;
	      my $minimal2 = TestCase::Minimal->new;
	      my $minimal3 = TestCase::Minimal->new;
	      
	      eval { copy_array_range_object([$minimal1, $minimal2, $minimal3], 1, 3); };
	      unless ($@) {
	        return 0;
	      }
	    }
    }

    return 1;
  }

  sub sort_byte : int () {
    # Sort array by asc order
    {
      my $nums = [(byte)2, 3, 1];
      
      SPVM::ArrayUtil->sort_byte($nums, 0, scalar @$nums, sub : int ($self : self, $a : byte, $b : byte) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_byte($nums, [(byte)1, 2, 3])) {
        return 0;
      }
    }

    # Sort array by asc order more long
    {
      my $nums = [(byte)5, 7, 9, 2, 4, 8, 1, 3, 6, 0];
      
      SPVM::ArrayUtil->sort_byte($nums, 0, scalar @$nums, sub : int ($self : self, $a : byte, $b : byte) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_byte($nums, [(byte)0, 1, 2, 3, 4, 5, 6, 7, 8, 9])) {
        return 0;
      }
    }

    # Sort array by asc order more long with same values
    {
      my $nums = [(byte)5, 7, 9, 2, 5, 4, 8, 1, 3, 6, 3, 0];
      
      SPVM::ArrayUtil->sort_byte($nums, 0, scalar @$nums, sub : int ($self : self, $a : byte, $b : byte) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_byte($nums, [(byte)0, 1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 9])) {
        return 0;
      }
    }

    # Sort byte array by desc order
    {
      my $nums = [(byte)2, 3, 1];
      
      SPVM::ArrayUtil->sort_byte($nums, 0, scalar @$nums, sub : int ($self : self, $a : byte, $b : byte) {
        return $b <=> $a;
      });
      
      unless (SPVM::ArrayUtil->equals_array_byte($nums, [(byte)3, 2, 1])) {
        return 0;
      }
    }

    # If length is 0, There is nothing to do
    {
      my $nums = [(byte)2, 3, 1];
      
      SPVM::ArrayUtil->sort_byte($nums, 0, 0, sub : int ($self : self, $a : byte, $b : byte) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_byte($nums, [(byte)2, 3, 1])) {
        return 0;
      }
    }
    
    # Sort partially
    {
      my $nums = [(byte)5, 2, 3, 1, -10];
      
      SPVM::ArrayUtil->sort_byte($nums, 1, 3, sub : int ($self : self, $a : byte, $b : byte) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_byte($nums, [(byte)5, 1, 2, 3, -10])) {
        return 0;
      }
    }

    # Exception - Array must be not undef
    {
      my $nums = [(byte)2, 3, 1];
      
      eval {
        SPVM::ArrayUtil->sort_byte(undef, 0, scalar @$nums, sub : int ($self : self, $a : byte, $b : byte) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }
    
    # Exception - Offset must be more than or equals to 0
    {
      my $nums = [(byte)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_byte($nums, -1, 3, sub : int ($self : self, $a : byte, $b : byte) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Length must be more than or equals to 0
    {
      my $nums = [(byte)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_byte($nums, 1, -1, sub : int ($self : self, $a : byte, $b : byte) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Offset + Length must be in the array range
    {
      my $nums = [(byte)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_byte($nums, 3, 3, sub : int ($self : self, $a : byte, $b : byte) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }
    
    $@ = undef;
    
    return 1;
  }

  sub sort_short : int () {
    # Sort array by asc order
    {
      my $nums = [(short)2, 3, 1];
      
      SPVM::ArrayUtil->sort_short($nums, 0, scalar @$nums, sub : int ($self : self, $a : short, $b : short) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_short($nums, [(short)1, 2, 3])) {
        return 0;
      }
    }

    # Sort array by asc order more long
    {
      my $nums = [(short)5, 7, 9, 2, 4, 8, 1, 3, 6, 0];
      
      SPVM::ArrayUtil->sort_short($nums, 0, scalar @$nums, sub : int ($self : self, $a : short, $b : short) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_short($nums, [(short)0, 1, 2, 3, 4, 5, 6, 7, 8, 9])) {
        return 0;
      }
    }

    # Sort array by asc order more long with same values
    {
      my $nums = [(short)5, 7, 9, 2, 5, 4, 8, 1, 3, 6, 3, 0];
      
      SPVM::ArrayUtil->sort_short($nums, 0, scalar @$nums, sub : int ($self : self, $a : short, $b : short) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_short($nums, [(short)0, 1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 9])) {
        return 0;
      }
    }

    # Sort short array by desc order
    {
      my $nums = [(short)2, 3, 1];
      
      SPVM::ArrayUtil->sort_short($nums, 0, scalar @$nums, sub : int ($self : self, $a : short, $b : short) {
        return $b <=> $a;
      });
      
      unless (SPVM::ArrayUtil->equals_array_short($nums, [(short)3, 2, 1])) {
        return 0;
      }
    }

    # If length is 0, There is nothing to do
    {
      my $nums = [(short)2, 3, 1];
      
      SPVM::ArrayUtil->sort_short($nums, 0, 0, sub : int ($self : self, $a : short, $b : short) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_short($nums, [(short)2, 3, 1])) {
        return 0;
      }
    }
    
    # Sort partially
    {
      my $nums = [(short)5, 2, 3, 1, -10];
      
      SPVM::ArrayUtil->sort_short($nums, 1, 3, sub : int ($self : self, $a : short, $b : short) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_short($nums, [(short)5, 1, 2, 3, -10])) {
        return 0;
      }
    }

    # Exception - Array must be not undef
    {
      my $nums = [(short)2, 3, 1];
      
      eval {
        SPVM::ArrayUtil->sort_short(undef, 0, scalar @$nums, sub : int ($self : self, $a : short, $b : short) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }
    
    # Exception - Offset must be more than or equals to 0
    {
      my $nums = [(short)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_short($nums, -1, 3, sub : int ($self : self, $a : short, $b : short) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Length must be more than or equals to 0
    {
      my $nums = [(short)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_short($nums, 1, -1, sub : int ($self : self, $a : short, $b : short) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Offset + Length must be in the array range
    {
      my $nums = [(short)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_short($nums, 3, 3, sub : int ($self : self, $a : short, $b : short) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }
    
    $@ = undef;
    
    return 1;
  }

  sub sort_int : int () {
    # Sort array by asc order
    {
      my $nums = [(int)2, 3, 1];
      
      SPVM::ArrayUtil->sort_int($nums, 0, scalar @$nums, sub : int ($self : self, $a : int, $b : int) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_int($nums, [(int)1, 2, 3])) {
        return 0;
      }
    }

    # Sort array by asc order more long
    {
      my $nums = [(int)5, 7, 9, 2, 4, 8, 1, 3, 6, 0];
      
      SPVM::ArrayUtil->sort_int($nums, 0, scalar @$nums, sub : int ($self : self, $a : int, $b : int) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_int($nums, [(int)0, 1, 2, 3, 4, 5, 6, 7, 8, 9])) {
        return 0;
      }
    }

    # Sort array by asc order more long with same values
    {
      my $nums = [(int)5, 7, 9, 2, 5, 4, 8, 1, 3, 6, 3, 0];
      
      SPVM::ArrayUtil->sort_int($nums, 0, scalar @$nums, sub : int ($self : self, $a : int, $b : int) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_int($nums, [(int)0, 1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 9])) {
        return 0;
      }
    }

    # Sort int array by desc order
    {
      my $nums = [(int)2, 3, 1];
      
      SPVM::ArrayUtil->sort_int($nums, 0, scalar @$nums, sub : int ($self : self, $a : int, $b : int) {
        return $b <=> $a;
      });
      
      unless (SPVM::ArrayUtil->equals_array_int($nums, [(int)3, 2, 1])) {
        return 0;
      }
    }

    # If length is 0, There is nothing to do
    {
      my $nums = [(int)2, 3, 1];
      
      SPVM::ArrayUtil->sort_int($nums, 0, 0, sub : int ($self : self, $a : int, $b : int) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_int($nums, [(int)2, 3, 1])) {
        return 0;
      }
    }
    
    # Sort partially
    {
      my $nums = [(int)5, 2, 3, 1, -10];
      
      SPVM::ArrayUtil->sort_int($nums, 1, 3, sub : int ($self : self, $a : int, $b : int) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_int($nums, [(int)5, 1, 2, 3, -10])) {
        return 0;
      }
    }

    # Exception - Array must be not undef
    {
      my $nums = [(int)2, 3, 1];
      
      eval {
        SPVM::ArrayUtil->sort_int(undef, 0, scalar @$nums, sub : int ($self : self, $a : int, $b : int) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }
    
    # Exception - Offset must be more than or equals to 0
    {
      my $nums = [(int)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_int($nums, -1, 3, sub : int ($self : self, $a : int, $b : int) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Length must be more than or equals to 0
    {
      my $nums = [(int)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_int($nums, 1, -1, sub : int ($self : self, $a : int, $b : int) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Offset + Length must be in the array range
    {
      my $nums = [(int)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_int($nums, 3, 3, sub : int ($self : self, $a : int, $b : int) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }
    
    $@ = undef;
    
    return 1;
  }

  sub sort_long : int () {
    # Sort array by asc order
    {
      my $nums = [(long)2, 3, 1];
      
      SPVM::ArrayUtil->sort_long($nums, 0, scalar @$nums, sub : int ($self : self, $a : long, $b : long) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_long($nums, [(long)1, 2, 3])) {
        return 0;
      }
    }

    # Sort array by asc order more long
    {
      my $nums = [(long)5, 7, 9, 2, 4, 8, 1, 3, 6, 0];
      
      SPVM::ArrayUtil->sort_long($nums, 0, scalar @$nums, sub : int ($self : self, $a : long, $b : long) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_long($nums, [(long)0, 1, 2, 3, 4, 5, 6, 7, 8, 9])) {
        return 0;
      }
    }

    # Sort array by asc order more long with same values
    {
      my $nums = [(long)5, 7, 9, 2, 5, 4, 8, 1, 3, 6, 3, 0];
      
      SPVM::ArrayUtil->sort_long($nums, 0, scalar @$nums, sub : int ($self : self, $a : long, $b : long) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_long($nums, [(long)0, 1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 9])) {
        return 0;
      }
    }

    # Sort long array by desc order
    {
      my $nums = [(long)2, 3, 1];
      
      SPVM::ArrayUtil->sort_long($nums, 0, scalar @$nums, sub : int ($self : self, $a : long, $b : long) {
        return $b <=> $a;
      });
      
      unless (SPVM::ArrayUtil->equals_array_long($nums, [(long)3, 2, 1])) {
        return 0;
      }
    }

    # If length is 0, There is nothing to do
    {
      my $nums = [(long)2, 3, 1];
      
      SPVM::ArrayUtil->sort_long($nums, 0, 0, sub : int ($self : self, $a : long, $b : long) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_long($nums, [(long)2, 3, 1])) {
        return 0;
      }
    }
    
    # Sort partially
    {
      my $nums = [(long)5, 2, 3, 1, -10];
      
      SPVM::ArrayUtil->sort_long($nums, 1, 3, sub : int ($self : self, $a : long, $b : long) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_long($nums, [(long)5, 1, 2, 3, -10])) {
        return 0;
      }
    }

    # Exception - Array must be not undef
    {
      my $nums = [(long)2, 3, 1];
      
      eval {
        SPVM::ArrayUtil->sort_long(undef, 0, scalar @$nums, sub : int ($self : self, $a : long, $b : long) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }
    
    # Exception - Offset must be more than or equals to 0
    {
      my $nums = [(long)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_long($nums, -1, 3, sub : int ($self : self, $a : long, $b : long) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Length must be more than or equals to 0
    {
      my $nums = [(long)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_long($nums, 1, -1, sub : int ($self : self, $a : long, $b : long) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Offset + Length must be in the array range
    {
      my $nums = [(long)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_long($nums, 3, 3, sub : int ($self : self, $a : long, $b : long) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }
    
    $@ = undef;
    
    return 1;
  }

  sub sort_float : int () {
    # Sort array by asc order
    {
      my $nums = [(float)2, 3, 1];
      
      SPVM::ArrayUtil->sort_float($nums, 0, scalar @$nums, sub : int ($self : self, $a : float, $b : float) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_float($nums, [(float)1, 2, 3])) {
        return 0;
      }
    }

    # Sort array by asc order more long
    {
      my $nums = [(float)5, 7, 9, 2, 4, 8, 1, 3, 6, 0];
      
      SPVM::ArrayUtil->sort_float($nums, 0, scalar @$nums, sub : int ($self : self, $a : float, $b : float) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_float($nums, [(float)0, 1, 2, 3, 4, 5, 6, 7, 8, 9])) {
        return 0;
      }
    }

    # Sort array by asc order more long with same values
    {
      my $nums = [(float)5, 7, 9, 2, 5, 4, 8, 1, 3, 6, 3, 0];
      
      SPVM::ArrayUtil->sort_float($nums, 0, scalar @$nums, sub : int ($self : self, $a : float, $b : float) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_float($nums, [(float)0, 1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 9])) {
        return 0;
      }
    }

    # Sort float array by desc order
    {
      my $nums = [(float)2, 3, 1];
      
      SPVM::ArrayUtil->sort_float($nums, 0, scalar @$nums, sub : int ($self : self, $a : float, $b : float) {
        return $b <=> $a;
      });
      
      unless (SPVM::ArrayUtil->equals_array_float($nums, [(float)3, 2, 1])) {
        return 0;
      }
    }

    # If length is 0, There is nothing to do
    {
      my $nums = [(float)2, 3, 1];
      
      SPVM::ArrayUtil->sort_float($nums, 0, 0, sub : int ($self : self, $a : float, $b : float) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_float($nums, [(float)2, 3, 1])) {
        return 0;
      }
    }
    
    # Sort partially
    {
      my $nums = [(float)5, 2, 3, 1, -10];
      
      SPVM::ArrayUtil->sort_float($nums, 1, 3, sub : int ($self : self, $a : float, $b : float) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_float($nums, [(float)5, 1, 2, 3, -10])) {
        return 0;
      }
    }

    # Exception - Array must be not undef
    {
      my $nums = [(float)2, 3, 1];
      
      eval {
        SPVM::ArrayUtil->sort_float(undef, 0, scalar @$nums, sub : int ($self : self, $a : float, $b : float) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }
    
    # Exception - Offset must be more than or equals to 0
    {
      my $nums = [(float)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_float($nums, -1, 3, sub : int ($self : self, $a : float, $b : float) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Length must be more than or equals to 0
    {
      my $nums = [(float)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_float($nums, 1, -1, sub : int ($self : self, $a : float, $b : float) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Offset + Length must be in the array range
    {
      my $nums = [(float)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_float($nums, 3, 3, sub : int ($self : self, $a : float, $b : float) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }
    
    $@ = undef;
    
    return 1;
  }

  sub sort_double : int () {
    # Sort array by asc order
    {
      my $nums = [(double)2, 3, 1];
      
      SPVM::ArrayUtil->sort_double($nums, 0, scalar @$nums, sub : int ($self : self, $a : double, $b : double) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_double($nums, [(double)1, 2, 3])) {
        return 0;
      }
    }

    # Sort array by asc order more long
    {
      my $nums = [(double)5, 7, 9, 2, 4, 8, 1, 3, 6, 0];
      
      SPVM::ArrayUtil->sort_double($nums, 0, scalar @$nums, sub : int ($self : self, $a : double, $b : double) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_double($nums, [(double)0, 1, 2, 3, 4, 5, 6, 7, 8, 9])) {
        return 0;
      }
    }

    # Sort array by asc order more long with same values
    {
      my $nums = [(double)5, 7, 9, 2, 5, 4, 8, 1, 3, 6, 3, 0];
      
      SPVM::ArrayUtil->sort_double($nums, 0, scalar @$nums, sub : int ($self : self, $a : double, $b : double) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_double($nums, [(double)0, 1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 9])) {
        return 0;
      }
    }

    # Sort double array by desc order
    {
      my $nums = [(double)2, 3, 1];
      
      SPVM::ArrayUtil->sort_double($nums, 0, scalar @$nums, sub : int ($self : self, $a : double, $b : double) {
        return $b <=> $a;
      });
      
      unless (SPVM::ArrayUtil->equals_array_double($nums, [(double)3, 2, 1])) {
        return 0;
      }
    }

    # If length is 0, There is nothing to do
    {
      my $nums = [(double)2, 3, 1];
      
      SPVM::ArrayUtil->sort_double($nums, 0, 0, sub : int ($self : self, $a : double, $b : double) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_double($nums, [(double)2, 3, 1])) {
        return 0;
      }
    }
    
    # Sort partially
    {
      my $nums = [(double)5, 2, 3, 1, -10];
      
      SPVM::ArrayUtil->sort_double($nums, 1, 3, sub : int ($self : self, $a : double, $b : double) {
        return $a <=> $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_double($nums, [(double)5, 1, 2, 3, -10])) {
        return 0;
      }
    }

    # Exception - Array must be not undef
    {
      my $nums = [(double)2, 3, 1];
      
      eval {
        SPVM::ArrayUtil->sort_double(undef, 0, scalar @$nums, sub : int ($self : self, $a : double, $b : double) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }
    
    # Exception - Offset must be more than or equals to 0
    {
      my $nums = [(double)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_double($nums, -1, 3, sub : int ($self : self, $a : double, $b : double) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Length must be more than or equals to 0
    {
      my $nums = [(double)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_double($nums, 1, -1, sub : int ($self : self, $a : double, $b : double) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Offset + Length must be in the array range
    {
      my $nums = [(double)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_double($nums, 3, 3, sub : int ($self : self, $a : double, $b : double) {
          return $a <=> $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }
    
    $@ = undef;
    
    return 1;
  }

  sub sort_string : int () {
    # Sort array by asc order
    {
      my $strings = [(string)2, 3, 1];
      
      SPVM::ArrayUtil->sort_string($strings, 0, scalar @$strings, sub : int ($self : self, $a : string, $b : string) {
        return $a cmp $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_string($strings, [(string)1, 2, 3])) {
        return 0;
      }
    }

    # Sort array by asc order more long
    {
      my $strings = [(string)5, 7, 9, 2, 4, 8, 1, 3, 6, 0];
      
      SPVM::ArrayUtil->sort_string($strings, 0, scalar @$strings, sub : int ($self : self, $a : string, $b : string) {
        return $a cmp $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_string($strings, [(string)0, 1, 2, 3, 4, 5, 6, 7, 8, 9])) {
        return 0;
      }
    }

    # Sort array by asc order more long with same values
    {
      my $strings = [(string)5, 7, 9, 2, 5, 4, 8, 1, 3, 6, 3, 0];
      
      SPVM::ArrayUtil->sort_string($strings, 0, scalar @$strings, sub : int ($self : self, $a : string, $b : string) {
        return $a cmp $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_string($strings, [(string)0, 1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 9])) {
        return 0;
      }
    }

    # Sort string array by desc order
    {
      my $strings = [(string)2, 3, 1];
      
      SPVM::ArrayUtil->sort_string($strings, 0, scalar @$strings, sub : int ($self : self, $a : string, $b : string) {
        return $b cmp $a;
      });
      
      unless (SPVM::ArrayUtil->equals_array_string($strings, [(string)3, 2, 1])) {
        return 0;
      }
    }

    # If length is 0, There is nothing to do
    {
      my $strings = [(string)2, 3, 1];
      
      SPVM::ArrayUtil->sort_string($strings, 0, 0, sub : int ($self : self, $a : string, $b : string) {
        return $a cmp $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_string($strings, [(string)2, 3, 1])) {
        return 0;
      }
    }
    
    # Sort partially
    {
      my $strings = [(string)5, 2, 3, 1, -10];
      
      SPVM::ArrayUtil->sort_string($strings, 1, 3, sub : int ($self : self, $a : string, $b : string) {
        return $a cmp $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_string($strings, [(string)5, 1, 2, 3, -10])) {
        return 0;
      }
    }

    # Sort length is differnt and contain empty string and undef
    {
      my $strings = ["11", "1", "2", undef, ""];
      
      SPVM::ArrayUtil->sort_string($strings, 0, scalar @$strings, sub : int ($self : self, $a : string, $b : string) {
        return $a cmp $b;
      });
      
      unless (SPVM::ArrayUtil->equals_array_string($strings, [(string)undef, "", "1", "11", "2"])) {
        return 0;
      }
    }

    # Exception - Array must be not undef
    {
      my $strings = [(string)2, 3, 1];
      
      eval {
        SPVM::ArrayUtil->sort_string(undef, 0, scalar @$strings, sub : int ($self : self, $a : string, $b : string) {
          return $a cmp $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }
    
    # Exception - Offset must be more than or equals to 0
    {
      my $strings = [(string)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_string($strings, -1, 3, sub : int ($self : self, $a : string, $b : string) {
          return $a cmp $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Length must be more than or equals to 0
    {
      my $strings = [(string)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_string($strings, 1, -1, sub : int ($self : self, $a : string, $b : string) {
          return $a cmp $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Offset + Length must be in the array range
    {
      my $strings = [(string)5, 2, 3, 1, -10];
      
      eval {
        SPVM::ArrayUtil->sort_string($strings, 3, 3, sub : int ($self : self, $a : string, $b : string) {
          return $a cmp $b;
        });
      };
      unless ($@) {
        return 0;
      }
    }
    
    $@ = undef;
    
    return 1;
  }

  sub new_minimal : TestCase::Minimal ($x : int, $y : int) {
    my $minimal = TestCase::Minimal->new;
    $minimal->set_x($x);
    $minimal->set_y($y);
    
    return $minimal;
  }
  
  sub sort_object : int () {
    
    # Sort array by asc order
    {
      my $objs = [new_minimal(2, 0), new_minimal(3, 0), new_minimal(1, 0)];
      
      SPVM::ArrayUtil->sort_object($objs, 0, scalar @$objs, sub : int ($self : self, $a : object, $b : object) {
        return ((TestCase::Minimal)$a)->x <=> ((TestCase::Minimal)$b)->x;
      });
      
      my $is_equals = SPVM::ArrayUtil->equals_array_object($objs, [new_minimal(1, 0), new_minimal(2, 0), new_minimal(3, 0)], sub : int ($self : self, $a : object, $b : object) {
        return ((TestCase::Minimal)$a)->x == ((TestCase::Minimal)$b)->x;
      });
      
      unless ($is_equals) {
        return 0;
      }
    }

    # Sort array by multiple conditions
    {
      my $objs = [new_minimal(2, 1), new_minimal(2, 2), new_minimal(1, 3)];

      SPVM::ArrayUtil->sort_object($objs, 0, scalar @$objs, sub : int ($self : self, $a : object, $b : object) {
        my $a_x = ((TestCase::Minimal)$a)->x;
        my $a_y = ((TestCase::Minimal)$a)->y;
        my $b_x = ((TestCase::Minimal)$b)->x;
        my $b_y = ((TestCase::Minimal)$b)->y;
        
        my $cmp = ((TestCase::Minimal)$a)->x <=> ((TestCase::Minimal)$b)->x;
        if ($cmp != 0) {
          return $cmp;
        }
        else {
          $cmp = ((TestCase::Minimal)$a)->y <=> ((TestCase::Minimal)$b)->y;
        }
        
        return $cmp;
      });

      my $is_equals = SPVM::ArrayUtil->equals_array_object($objs, [new_minimal(1, 3), new_minimal(2, 1), new_minimal(2, 2)], sub : int ($self : self, $a : object, $b : object) {
        if (((TestCase::Minimal)$a)->x == ((TestCase::Minimal)$b)->x && ((TestCase::Minimal)$a)->y == ((TestCase::Minimal)$b)->y) {
          return 1;
        }
        else {
          return 0;
        }
      });
      
      unless ($is_equals) {
        return 0;
      }
    }

    # Sort array by desc order
    {
      my $objs = [new_minimal(2, 0), new_minimal(3, 0), new_minimal(1, 0)];
      
      SPVM::ArrayUtil->sort_object($objs, 0, scalar @$objs, sub : int ($self : self, $a : object, $b : object) {
        return ((TestCase::Minimal)$b)->x <=> ((TestCase::Minimal)$a)->x;
      });
      
      my $is_equals = SPVM::ArrayUtil->equals_array_object($objs, [new_minimal(3, 0), new_minimal(2, 0), new_minimal(1, 0)], sub : int ($self : self, $a : object, $b : object) {
        return ((TestCase::Minimal)$a)->x == ((TestCase::Minimal)$b)->x;
      });
      
      unless ($is_equals) {
        return 0;
      }
    }

    # If length is 0, There is nothing to do
    {
      my $objs = [new_minimal(2, 0), new_minimal(3, 0), new_minimal(1, 0)];
      
      SPVM::ArrayUtil->sort_object($objs, 0, 0, sub : int ($self : self, $a : object, $b : object) {
        return ((TestCase::Minimal)$a)->x <=> ((TestCase::Minimal)$b)->x;
      });
      
      my $is_equals = SPVM::ArrayUtil->equals_array_object($objs, [new_minimal(2, 0), new_minimal(3, 0), new_minimal(1, 0)], sub : int ($self : self, $a : object, $b : object) {
        return ((TestCase::Minimal)$a)->x == ((TestCase::Minimal)$b)->x;
      });
      unless ($is_equals) {
        return 0;
      }
    }
    
    # Sort partially
    {
      my $objs = [new_minimal(5, 0), new_minimal(2, 0), new_minimal(3, 0), new_minimal(1, 0), new_minimal(-10, 0)];
      
      SPVM::ArrayUtil->sort_object($objs, 1, 3, sub : int ($self : self, $a : object, $b : object) {
        return ((TestCase::Minimal)$a)->x <=> ((TestCase::Minimal)$b)->x;
      });
      
      my $is_equals = SPVM::ArrayUtil->equals_array_object(
        $objs,
        [new_minimal(5, 0), new_minimal(1, 0), new_minimal(2, 0), new_minimal(3, 0), new_minimal(-10, 0)],
        sub : int ($self : self, $a : object, $b : object) {
          return ((TestCase::Minimal)$a)->x == ((TestCase::Minimal)$b)->x;
        }
      );
      unless ($is_equals) {
        return 0;
      }
    }

    # Exception - Array must be not undef
    {
      my $objs = [new_minimal(2, 0), new_minimal(3, 0), new_minimal(1, 0)];
      
      eval {
        SPVM::ArrayUtil->sort_object(undef, 0, scalar @$objs, sub : int ($self : self, $a : object, $b : object) {
          return ((TestCase::Minimal)$a)->x <=> ((TestCase::Minimal)$b)->x;
        });
      };
      unless ($@) {
        return 0;
      }
    }
    
    # Exception - Offset must be more than or equals to 0
    {
      my $objs = [new_minimal(2, 0), new_minimal(3, 0), new_minimal(1, 0)];
      
      eval {
        SPVM::ArrayUtil->sort_object($objs, -1, 3, sub : int ($self : self, $a : object, $b : object) {
          return ((TestCase::Minimal)$a)->x <=> ((TestCase::Minimal)$b)->x;
        });
      };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Length must be more than or equals to 0
    {
      my $objs = [new_minimal(5, 0), new_minimal(2, 0), new_minimal(3, 0), new_minimal(1, 0), new_minimal(-10, 0)];
      
      eval {
        SPVM::ArrayUtil->sort_object($objs, 1, -1, sub : int ($self : self, $a : object, $b : object) {
          return ((TestCase::Minimal)$a)->x <=> ((TestCase::Minimal)$b)->x;
        });
      };
      unless ($@) {
        return 0;
      }
    }

    # Exception - Offset + Length must be in the array range
    {
      my $objs = [new_minimal(5, 0), new_minimal(2, 0), new_minimal(3, 0), new_minimal(1, 0), new_minimal(-10, 0)];
      
      eval {
        SPVM::ArrayUtil->sort_object($objs, 3, 3, sub : int ($self : self, $a : object, $b : object) {
          return ((TestCase::Minimal)$a)->x <=> ((TestCase::Minimal)$b)->x;
        });
      };
      unless ($@) {
        return 0;
      }
    }
    
    $@ = undef;

    return 1;
  }
}