class TestCase::Module::ByteList {
  use ByteList;
  use Fn;
  use Array;
  
  # Fields
  static method fields : int () {
    {
      my $list = ByteList->new([(byte)1, 2, 3]);
      
      # length
      my $length = $list->length;
      unless ($length == 3) {
        return 0;
      }
      
    }
    
    return 1;
  }
  
  # Class methods
  static method new : int () {
    # new with array
    {
      my $list = ByteList->new([(byte)3, 5, Fn->BYTE_MAX]);
      
      unless ($list->get(0) == 3) {
        return 0;
      }
      
      unless ($list->get(1) == 5) {
        return 0;
      }
      
      unless ($list->get(2) == Fn->BYTE_MAX) {
        return 0;
      }
      
      my $length = $list->length;
      unless ($length == 3) {
        return 0;
      }
      
    }
    
    # capcity
    {
      my $list = ByteList->new([(byte)3, 5, Fn->BYTE_MAX], 10);
      
      unless ($list->get(0) == 3) {
        return 0;
      }
      
      unless ($list->get(1) == 5) {
        return 0;
      }
      
      unless ($list->get(2) == Fn->BYTE_MAX) {
        return 0;
      }
      
      my $length = $list->length;
      unless ($length == 3) {
        return 0;
      }
      
      # capacity
      unless ($list->capacity == 10) {
        return 0;
      }
    }
    
    # new with undef
    {
      my $list = ByteList->new((byte[])undef);
      
      unless ($list->length == 0) {
        return 0;
      }
    }
    
    # new without argument
    {
      my $list = ByteList->new;
      
      unless ($list->length == 0) {
        return 0;
      }
    }
    
    # extra
    {
      {
        my $list = ByteList->new([(byte)3]);
        
        unless ($list->get(0) == 3) {
          return 0;
        }
      }
      {
        my $list = ByteList->new([(byte)3, 4]);
        
        unless ($list->get(0) == 3 && $list->get(1) == 4) {
          return 0;
        }
      }
    }
    # length
    {
      my $list = ByteList->new_len(0);
      
      $list->unshift(3);
      $list->unshift(5);
      $list->unshift(Fn->BYTE_MAX);
      
      my $length = $list->length;
      unless ($length == 3) {
        return 0;
      }
    }
    
    # Countable interface
    {
      my $list = ByteList->new_len(3);
      
      unless ($list isa Countable) {
        return 0;
      }
      
      my $length = @$list;
      
      unless ($length == 3) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method new_len : int () {
    {
      my $list = ByteList->new_len(32);
      
      unless ($list->length == 32) {
        return 0;
      }
    }
    
    {
      my $list = ByteList->new_len(32, 10);
      
      unless ($list->length == 32) {
        return 0;
      }
    }
    
    {
      my $list = ByteList->new_len(0);
      
      unless ($list->length == 0) {
        return 0;
      }
    }
    
    {
      my $list = ByteList->new_len(0, 10);
      
      unless ($list->length == 0) {
        return 0;
      }
      unless ($list->capacity == 10) {
        return 0;
      }
    }
    
    {
      eval { ByteList->new_len(-1); };
      unless (Fn->contains($@, "The length \$length must be greater than or equal to 0")) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method new_ref : int () {
    # new with array
    { 
      my $array = [(byte)3, 5, Fn->BYTE_MAX()];
      my $list = ByteList->new_ref($array);
      
      unless ($list->get(0) == 3) {
        return 0;
      }
      
      unless ($list->get(1) == 5) {
        return 0;
      }
      
      unless ($list->get(2) == Fn->BYTE_MAX()) {
        return 0;
      }
      
      my $length = $list->length;
      unless ($length == 3) {
        return 0;
      }
      
      unless ($list->get_array == $array) {
        return 0;
      }
      
    }
    
    return 1;
  }
  
  # Instance methods
  static method get : int () {
    {
      my $list = ByteList->new([(byte)3, 5, Fn->BYTE_MAX]);
      
      unless ($list->get(0) == 3) {
        return 0;
      }
      
      unless ($list->get(-3) == 3) {
        return 0;
      }
      
      unless ($list->get(0) isa int) {
        return 0;
      }
      
      unless ($list->get(1) == 5) {
        return 0;
      }
      
      unless ($list->get(2) == Fn->BYTE_MAX) {
        return 0;
      }
      
      my $length = $list->length;
      unless ($length == 3) {
        return 0;
      }
      
      eval { $list->get(-($list->length + 1)); };
      unless (Fn->contains($@, "The index \$index must be greater than or equal to 0")) {
        return 0;
      }
      
      eval { $list->get(3); };
      unless (Fn->contains($@, "The index \$index must be less than the length of \$list")) {
        return 0;
      }
      
      
    }
    
    return 1;
  }
  
  static method insert : int () {
    # Insert to first
    {
      my $list = ByteList->new([(byte)1, 2, 3]);
      $list->insert(0 => 4);
      unless (Array->equals_byte($list->to_array, [(byte)4, 1, 2, 3])) {
        return 0;
      }
    }
    
    # Insert
    {
      my $list = ByteList->new([(byte)1, 2, 3]);
      $list->insert(2 => 4);
      unless (Array->equals_byte($list->to_array, [(byte)1, 2, 4, 3])) {
        return 0;
      }
    }
    
    # Insert to last
    {
      my $list = ByteList->new([(byte)1, 2, 3]);
      $list->insert(3 => 4);
      unless (Array->equals_byte($list->to_array, [(byte)1, 2, 3, 4])) {
        return 0;
      }
    }
    
    # Extend
    {
      my $list = ByteList->new([(byte)1, 2, 3]);
      $list->insert(0 => 4);
    }
    
    # Exception - insert to -1
    {
      my $list = ByteList->new([(byte)1, 2, 3]);
      eval {  $list->insert(-1 => 2); };
      unless (Fn->contains($@, "The index \$index must be greater than or equal to 0")) {
        return 0;
      }
    }
    
    # Exception - insert to length + 1
    {
      my $list = ByteList->new([(byte)1, 2, 3]);
      eval { $list->insert(4 => 2); };
      unless (Fn->contains($@, "The index \$index must be less than or equal to the length of \$list")) {
        return 0;
      }
    }
    
    
    
    return 1;
  }
  
  static method pop : int () {
    {
      my $list = ByteList->new_len(0);
      
      $list->push(3);
      $list->push(5);
      $list->push(Fn->BYTE_MAX);
      
      my $pop0 = $list->pop;
      unless ($pop0 == Fn->BYTE_MAX) {
        return 0;
      }
      unless ($pop0 isa int) {
        return 0;
      }
      
      unless ($list->pop == 5) {
        return 0;
      }
      
      unless ($list->pop == 3) {
        return 0;
      }
      
      my $length = $list->length;
      unless ($length == 0) {
        return 0;
      }
      
      {
        my $list = ByteList->new_len(0);
        eval { $list->pop; };
        unless (Fn->contains($@, "The length of the list \$list must be greater than 0")) {
          return 0;
        }
      }
    }
    
    
    
    return 1;
  }
  
  static method push : int () {
    {
      my $list = ByteList->new_len(0);
      
      $list->push(3);
      $list->push(5);
      $list->push(Fn->BYTE_MAX);
      
      my $length = $list->length;
      unless ($length == 3) {
        return 0;
      }
      
      unless ($list->get(0) == 3 && $list->get(1) == 5 && $list->get(2) == Fn->BYTE_MAX) {
        return 0;
      }
    }
    
    # internal _extend tests
    {
      my $list = ByteList->new_len(0);
      
      for (my $i = 0; $i < 100; $i++) {
        $list->push(1);
      }
      
      my $length = $list->length;
      unless ($length == 100) {
        return 0;
      }
      
      for (my $i = 0; $i < 100; $i++) {
        unless ($list->get($i) == 1) {
          return 0;
        }
      }
    }
    
    
    return 1;
  }
  
  static method remove : int () {
    # Remove
    {
      my $list = ByteList->new([(byte)1, 2, 3, 4]);
      my $value = $list->remove(1);
      unless (Array->equals_byte($list->to_array, [(byte)1, 3, 4])) {
        return 0;
      }
      unless ($value == 2) {
        return 0;
      }
    }
    
    # Remove last
    {
      my $list = ByteList->new([(byte)1, 2, 3]);
      $list->remove(2);
      unless (Array->equals_byte($list->to_array, [(byte)1, 2])) {
        return 0;
      }
    }
    
    # Remove first
    {
      my $list = ByteList->new([(byte)1, 2, 3]);
      $list->remove(0);
      unless (Array->equals_byte($list->to_array, [(byte)2, 3])) {
        return 0;
      }
    }
    
    # Exception - remove to -1
    {
      my $list = ByteList->new([(byte)1, 2, 3]);
      eval { $list->remove(-1); };
      unless (Fn->contains($@, "The index \$index must be greater than or equal to 0")) {
        return 0;
      }
    }
    
    
    # Exception - remove to length
    {
      my $list = ByteList->new([(byte)1, 2, 3]);
      eval { $list->remove(3); };
      unless (Fn->contains($@, "The index \$index must be less than the length of \$list")) {
        return 0;
      }
    }
    
    
    
    return 1;
  }
  
  static method replace : int () {
    {
      my $list = ByteList->new([(byte)1, 2, 3, 4]);
      $list->replace(1, 2, undef);
      unless (Array->equals_byte($list->to_array, [(byte)1, 4])) {
        return 0;
      }
    }
    {
      my $list = ByteList->new([(byte)1, 2, 3, 4]);
      $list->replace(1, 2, [(byte)20, 30]);
      unless (Array->equals_byte($list->to_array, [(byte)1, 20, 30, 4])) {
        return 0;
      }
    }
    
    {
      my $list = ByteList->new([(byte)1, 2, 3, 4]);
      $list->replace(0, 2, [(byte)10, 20]);
      unless (Array->equals_byte($list->to_array, [(byte)10, 20, 3, 4])) {
        return 0;
      }
    }
    
    {
      my $list = ByteList->new([(byte)1, 2, 3, 4]);
      $list->replace(2, 2, [(byte)30, 40]);
      unless (Array->equals_byte($list->to_array, [(byte)1, 2, 30, 40])) {
        return 0;
      }
    }
    
    {
      my $list = ByteList->new([(byte)1, 2, 3, 4]);
      $list->replace(4, 0, [(byte)50, 60]);
      unless (Array->equals_byte($list->to_array, [(byte)1, 2, 3, 4, 50, 60])) {
        return 0;
      }
    }
    
    {
      my $list = ByteList->new([(byte)1, 2, 3, 4]);
      eval { $list->replace(-1, 3, [(byte)30, 40]); };
      unless (Fn->contains($@, "The offset \$offset must be greater than or equal to 0")) {
        return 0;
      }
    }
    
    {
      my $list = ByteList->new([(byte)1, 2, 3, 4]);
      eval { $list->replace(2, 3, [(byte)30, 40, 50]); };
      unless (Fn->contains($@, "\$offset + \$removing length must be less than or equal to the length of \$list")) {
        return 0;
      }
    }
    
    {
      my $list = ByteList->new([(byte)1]);
      $list->replace(1, 0, [(byte)2, 3]);
      unless (Array->equals_byte($list->to_array, [(byte)1, 2, 3])) {
        return 0;
      }
    }
    
    {
      my $list = ByteList->new([(byte)1]);
      eval { $list->replace(2, 0, [(byte)1, 2]); };
      unless (Fn->contains($@, "\$offset + \$removing length must be less than or equal to the length of \$list")) {
        return 0;
      }
    }
    {
      my $list = ByteList->new([(byte)1]);
      eval { $list->replace(1, 2, [(byte)1, 2]); };
      unless (Fn->contains($@, "\$offset + \$removing length must be less than or equal to the length of \$list")) {
        return 0;
      }
    }
    
    {
      my $list = ByteList->new([(byte)1]);
      eval { $list->replace(2, 2, [(byte)1, 2]); };
      unless (Fn->contains($@, "\$offset + \$removing length must be less than or equal to the length of \$list")) {
        return 0;
      }
    }
    
    
    
    return 1;
  }
  
  static method splice : int () {
  
    {
      my $list = ByteList->new([(byte)1, 2, 3, 4]);
      my $removed = $list->splice(1, 2, [(byte)20, 30]);
      
      unless (Array->equals_byte($list->to_array, [(byte)1, 20, 30, 4])) {
        return 0;
      }
      
      unless (Array->equals_byte($removed, [(byte)2, 3])) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method reserve : int () {
    {
      my $list = ByteList->new([(byte)1]);
      $list->reserve(4);
      unless ($list->capacity == 4) {
        return 0;
      }
      $list->reserve(0);
      unless ($list->capacity == 4) {
        return 0;
      }
    }
    {
      my $list = ByteList->new([(byte)1, 2, 3]);
      my $values = $list->get_array;
      my $array = $list->to_array;
      $list->reserve(5);
      unless ($list->capacity == 5) {
        return 0;
      }
      
      unless (Array->equals_byte($list->to_array, $array)) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method resize : int () {
    my $a = (byte)1;
    my $b = (byte)2;
    my $c = (byte)3;

    # 3 to 3
    {
      my $list = ByteList->new(new byte[0]);
      $list->push($a);
      $list->push($b);
      $list->push($c);
      $list->resize(3);
      unless ($list->length == 3) {
        return 0;
      }
      unless ($list->get(0) == $a && $list->get(1) == $b && $list->get(2) == $c) {
        return 0;
      }
    }
    
    # 3 to 0
    {
      my $list = ByteList->new(new byte[0]);
      $list->push($a);
      $list->push($b);
      $list->push($c);
      $list->resize(0);
      unless ($list->length == 0) {
        return 0;
      }
    }

    
    # 3 to 4
    {
      my $list = ByteList->new(new byte[0]);
      $list->push($a);
      $list->push($b);
      $list->push($c);
      $list->resize(4);
      unless ($list->length == 4) {
        return 0;
      }
      unless ($list->get(3) == 0 && $list->get(0) == $a && $list->get(1) == $b && $list->get(2) == $c) {
        return 0;
      }
    }
    
    # 3 to 32(over capacity)
    {
      my $list = ByteList->new(new byte[0]);
      $list->push($a);
      $list->push($b);
      $list->push($c);
      $list->resize(32);
      unless ($list->length == 32) {
        return 0;
      }
      unless ($list->get(3) == 0 && $list->get(31) == 0) {
        return 0;
      }
    }

    # 3 to 2 and 2 to 3 again
    {
      my $list = ByteList->new([(byte)1, 2, 3]);
      $list->resize(2);
      unless ($list->length == 2) {
        return 0;
      }
      
      $list->resize(3);
      unless ($list->length == 3) {
        return 0;
      }
      unless ($list->get(2) == 0) {
        return 0;
      }
    }
    
    # Exception - New length must be greater than or equal to 0
    {
      my $list = ByteList->new(new byte[0]);
      $list->push($a);
      $list->push($b);
      $list->push($c);
      eval { $list->resize(-1); };
      unless (Fn->contains($@, "The new length \$new_length must be greater than or equal to 0")) {
        return 0;
      }
    }
    
    
    return 1;
  }
  
  static method set : int () {
    {
      my $list = ByteList->new([(byte)0, 0, 0]);
      
      $list->set(0 => 3);
      $list->set(1 => 5);
      $list->set(2 => Fn->BYTE_MAX);
      
      unless ($list->get(0) == 3) {
        return 0;
      }

      unless ($list->get(1) == 5) {
        return 0;
      }

      unless ($list->get(2) == Fn->BYTE_MAX) {
        return 0;
      }
      
      my $length = $list->length;
      unless ($length == 3) {
        return 0;
      }
      
      eval { $list->set(-($list->length + 1), 1); };
      unless (Fn->contains($@,"The index \$index must be greater than or equal to 0")) {
        return 0;
      }
      
      eval { $list->set(3, 1); };
      unless (Fn->contains($@, "The index \$index must be less than the length of \$list")) {
        return 0;
      }
      
      
    }
    
    {
      my $list = ByteList->new([(byte)0, 0, 0]);
      
      $list->set(-1 => 3);
      
      unless ($list->get($list->length - 1) == 3) {
        return 0;
      }
      
    }
    
    return 1;
  }
  
  static method shift : int () {
    # shift
    {
      my $list = ByteList->new_len(0);
      
      $list->unshift(3);
      $list->unshift(5);
      $list->unshift(Fn->BYTE_MAX);
      
      unless ($list->shift == Fn->BYTE_MAX) {
        return 0;
      }
      
      unless ($list->shift == 5) {
        return 0;
      }
      
      unless ($list->shift == 3) {
        return 0;
      }
      
      my $length = $list->length;
      unless ($length == 0) {
        return 0;
      }
      
      eval { $list->shift; };
      unless (Fn->contains($@, "The length of the list \$list must be greater than 0")) {
        return 0;
      }
      
    }
    
    return 1;
  }
  
  static method to_array : int () {
    {
      my $list = ByteList->new([(byte)3, 5, Fn->BYTE_MAX]);
      
      my $array = $list->to_array;
      
      unless ($array isa byte[]) {
        return 0;
      }
      
      unless ($array->[0] == 3) {
        return 0;
      }

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

      unless ($array->[2] == Fn->BYTE_MAX) {
        return 0;
      }
      
      my $length = @$array;
      unless ($length == 3) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method get_array : int () {
    my $list = ByteList->new([(byte)1, 2, 3]);
    
    my $array = $list->get_array;
    $array->[2] = 4;
    
    unless ($list->get_array->[0] == 1) {
      return 0;
    }
    unless ($list->get_array->[1] == 2) {
      return 0;
    }
    unless ($list->get_array->[2] == 4) {
      return 0;
    }
    
    return 1;
  }
  
  static method unshift : int () {
    # unshift
    {
      my $list = ByteList->new_len(0);
      
      $list->unshift(3);
      $list->unshift(5);
      $list->unshift(Fn->BYTE_MAX);
      
      my $length = $list->length;
      unless ($length == 3) {
        return 0;
      }
      
      unless ($list->get(0) == Fn->BYTE_MAX && $list->get(1) == 5 && $list->get(2) == 3) {
        return 0;
      }
    }
    
    # internal _extend tests
    {
      my $list = ByteList->new_len(0);
      
      for (my $i = 0; $i < 100; $i++) {
        $list->unshift(1);
      }
      
      my $length = $list->length;
      unless ($length == 100) {
        return 0;
      }
      
      for (my $i = 0; $i < 100; $i++) {
        unless ($list->get($i) == 1) {
          return 0;
        }
      }
    }
    
    return 1;
  }
  
  # Unneeded
  static method length : int () {
    return 1;
  }
  
  static method clone : int () {
    
    {
      my $array = [(byte)1, 2];
      my $capacity = 3;
      
      my $list = ByteList->new($array, $capacity);
      
      my $clone = $list->clone;
      
      unless ($clone is_type ByteList) {
        return 0;
      }
      
      unless ($clone->length == $list->length) {
        return 0;
      }
      
      unless ($clone->capacity == $list->capacity) {
        return 0;
      }
      
      if ($clone == $list) {
        return 0;
      }
      
      unless (Array->equals($array, $clone->to_array)) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method push_ : int () {
    
    {
      my $list = ByteList->new_len(0);
      
      $list->push_([(byte)3, 5, Fn->BYTE_MAX]);
      
      my $length = $list->length;
      unless ($length == 3) {
        return 0;
      }
      
      unless ($list->get(0) == 3 && $list->get(1) == 5 && $list->get(2) == Fn->BYTE_MAX) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method unshift_ : int () {
    {
      my $list = ByteList->new_len(0);
      
      $list->unshift_([(byte)3, 5, Fn->BYTE_MAX]);
      
      my $length = $list->length;
      unless ($length == 3) {
        return 0;
      }
      
      unless ($list->get(0) == 3 && $list->get(1) == 5 && $list->get(2) == Fn->BYTE_MAX) {
        return 0;
      }
    }
    
    return 1;
  }
  
}