package TestCase::Lib::SPVM::StringList {
  use SPVM::StringList;
  use SPVM::Util (equals_strarray);

  sub new : int () {
    {
      my $list = SPVM::StringList->new([(string)"abc", "def", "ABC"]);
      
      unless ($list->get(0) eq "abc") {
        return 0;
      }
      
      unless ($list->get(1) eq "def") {
        return 0;
      }

      unless ($list->get(2) eq "ABC") {
        return 0;
      }
      
      my $length = $list->length;
      unless ($length == 3) {
        return 0;
      }
    }
    
    return 1;
  }

  sub new_capacity : int () {
    {
      my $list = SPVM::StringList->new_capacity(32);
      
      unless ($list->length == 0) {
        return 0;
      }
      
      unless ($list->capacity == 32) {
        return 0;
      }
    }
    
    return 1;
  }

  sub new_len : int () {
    {
      my $list = SPVM::StringList->new_len(32);
      
      unless ($list->length == 32) {
        return 0;
      }
      
      unless ($list->capacity == 32) {
        return 0;
      }
    }
    
    return 1;
  }

  sub insert : int () {
    # Insert to first
    {
      my $list = SPVM::StringList->new([(string)"1", "2", "3"]);
      $list->insert(0 => "4");
      unless (equals_strarray($list->to_array, [(string)"4", "1", "2", "3"])) {
        return 0;
      }
    }

    # Insert
    {
      my $list = SPVM::StringList->new([(string)"1", "2", "3"]);
      $list->insert(2 => "4");
      unless (equals_strarray($list->to_array, [(string)"1", "2", "4", "3"])) {
        return 0;
      }
    }

    # Insert to last
    {
      my $list = SPVM::StringList->new([(string)"1", "2", "3"]);
      $list->insert(3 => "4");
      unless (equals_strarray($list->to_array, [(string)"1", "2", "3", "4"])) {
        return 0;
      }
    }

    # Extend
    {
      my $list = SPVM::StringList->new([(string)"1", "2", "3"]);
      $list->insert(0 => "4");
    }
    
    # Exception - insert to -1
    eval {
      my $list = SPVM::StringList->new([(string)"1", "2", "3"]);
      $list->insert(-1 => "2");
    };
    unless ($@) {
      return 0;
    }
    $@ = undef;

    # Exception - insert to length + 1
    eval {
      my $list = SPVM::StringList->new([(string)"1", "2", "3"]);
      $list->insert(4 => "2");
    };
    unless ($@) {
      return 0;
    }
    $@ = undef;
    
    return 1;
  }

  sub remove : int () {
    # Remove
    {
      my $list = SPVM::StringList->new([(string)"1", "2", "3", "4"]);
      my $value = $list->remove(1);
      unless (equals_strarray($list->to_array, [(string)"1", "3", "4"])) {
        return 0;
      }
      unless ($value eq "2") {
        return 0;
      }
    }

    # Remove last
    {
      my $list = SPVM::StringList->new([(string)"1", "2", "3"]);
      $list->remove(2);
      unless (equals_strarray($list->to_array, [(string)"1", "2"])) {
        return 0;
      }
    }

    # Remove first
    {
      my $list = SPVM::StringList->new([(string)"1", "2", "3"]);
      $list->remove(0);
      unless (equals_strarray($list->to_array, [(string)"2", "3"])) {
        return 0;
      }
    }

    # Exception - remove to -1
    eval {
      my $list = SPVM::StringList->new([(string)"1", "2", "3"]);
      $list->remove(-1);
    };
    unless ($@) {
      return 0;
    }
    $@ = undef;

    # Exception - remove to length
    eval {
      my $list = SPVM::StringList->new([(string)"1", "2", "3"]);
      $list->remove(3);
    };
    unless ($@) {
      return 0;
    }
    $@ = undef;
    
    return 1;
  }

  sub to_array : int () {
    {
      my $list = SPVM::StringList->new([(string)"abc", "def", "ABC"]);
      
      my $array = $list->to_array;
      
      unless ($array isa string[]) {
        return 0;
      }
      
      unless ($array->[0] eq "abc") {
        return 0;
      }

      unless ($array->[1] eq "def") {
        return 0;
      }

      unless ($array->[2] eq "ABC") {
        return 0;
      }
      
      my $length = @$array;
      unless ($length == 3) {
        return 0;
      }
    }
    
    return 1;
  }

  sub get : int () {
    {
      my $list = SPVM::StringList->new([(string)"abc", "def", "ABC"]);
      
      unless ($list->get(0) eq "abc") {
        return 0;
      }

      unless ($list->get(0) isa string) {
        return 0;
      }

      unless ($list->get(1) eq "def") {
        return 0;
      }

      unless ($list->get(2) eq "ABC") {
        return 0;
      }
      
      my $length = $list->length;
      unless ($length == 3) {
        return 0;
      }
      
      eval {
        $list->get(-1);
      };
      unless ($@) {
        return 0;
      }
      
      eval {
        $list->get(3);
      };
      unless ($@) {
        return 0;
      }
      
      $@ = undef;
    }
    
    return 1;
  }

  sub set : int () {
    {
      my $list = SPVM::StringList->new([(string)0, 0, 0]);
      
      $list->set(0 => "abc");
      $list->set(1 => "def");
      $list->set(2 => "ABC");
      
      unless ($list->get(0) eq "abc") {
        return 0;
      }

      unless ($list->get(1) eq "def") {
        return 0;
      }

      unless ($list->get(2) eq "ABC") {
        return 0;
      }
      
      my $length = $list->length;
      unless ($length == 3) {
        return 0;
      }
      
      eval {
        $list->get(-1);
      };
      unless ($@) {
        return 0;
      }
      
      eval {
        $list->get(3);
      };
      unless ($@) {
        return 0;
      }
      
      $@ = undef;
    }
    
    return 1;
  }

  sub push : int () {
    # push
    {
      my $list = SPVM::StringList->new_len(0);
      
      $list->push("abc");
      $list->push("def");
      $list->push("ABC");
      
      my $length = $list->length;
      unless ($length == 3) {
        return 0;
      }
      
      unless ($list->get(0) eq "abc" && $list->get(1) eq "def" && $list->get(2) eq "ABC") {
        return 0;
      }
    }
    
    # internal _extend tests
    {
      my $list = SPVM::StringList->new_len(0);
      
      for (my $i = 0; $i < 100; $i++) {
        $list->push("p");
      }
      
      my $length = $list->length;
      unless ($length == 100) {
        return 0;
      }
      
      for (my $i = 0; $i < 100; $i++) {
        unless ($list->get($i) eq "p") {
          return 0;
        }
      }
    }
    
    
    return 1;
  }

  sub pop : int () {
    # pop
    {
      my $list = SPVM::StringList->new_len(0);
      
      $list->push("abc");
      $list->push("def");
      $list->push("ABC");
      
      my $pop0 = $list->pop;
      unless ($pop0 eq "ABC") {
        return 0;
      }
      unless ($pop0 isa string) {
        return 0;
      }

      unless ($list->pop eq "def") {
        return 0;
      }

      unless ($list->pop eq "abc") {
        return 0;
      }
      
      my $length = $list->length;
      unless ($length == 0) {
        return 0;
      }
      
      eval {
        $list->pop;
      };
      unless ($@) {
        return 0;
      }
      $@ = undef;
    }
    
    return 1;
  }

  sub unshift : int () {
    # unshift
    {
      my $list = SPVM::StringList->new_len(0);
      
      $list->unshift("abc");
      $list->unshift("def");
      $list->unshift("ABC");
      
      my $length = $list->length;
      unless ($length == 3) {
        return 0;
      }
      
      unless ($list->get(0) eq "ABC") {
        return 0;
      }
      unless ($list->get(1) eq "def") {
        return 0;
      }
      unless ($list->get(2) eq "abc") {
        return 0;
      }
    }
    
    # internal _extend tests
    {
      my $list = SPVM::StringList->new_len(0);
      
      for (my $i = 0; $i < 100; $i++) {
        $list->unshift("p");
      }
      
      my $length = $list->length;
      unless ($length == 100) {
        return 0;
      }
      
      for (my $i = 0; $i < 100; $i++) {
        unless ($list->get($i) eq "p") {
          return 0;
        }
      }
    }
    
    return 1;
  }

  sub shift : int () {
    # shift
    {
      my $list = SPVM::StringList->new_len(0);
      
      $list->unshift("abc");
      $list->unshift("def");
      $list->unshift("ABC");
      
      unless ($list->shift eq "ABC") {
        return 0;
      }

      unless ($list->shift eq "def") {
        return 0;
      }

      unless ($list->shift eq "abc") {
        return 0;
      }
      
      my $length = $list->length;
      unless ($length == 0) {
        return 0;
      }
      
      eval {
        $list->shift;
      };
      unless ($@) {
        return 0;
      }
      $@ = undef;
    }
    
    return 1;
  }

  sub length : int () {
    # length
    {
      my $list = SPVM::StringList->new_len(0);
      
      $list->unshift("abc");
      $list->unshift("def");
      $list->unshift("ABC");
      
      my $length = $list->length;
      unless ($length == 3) {
        return 0;
      }
    }
    
    return 1;
  }

}
