package TestCase::Lib::SPVM::Regex {
  use SPVM::Regex;
  
  sub compile : int () {
    my $re = SPVM::Regex->new("abc");
    
    return 1;
  }

  sub match_char_class_range : int ()  {
    # Match char class range
    {
      my $re = SPVM::Regex->new("[0-9]+");
      my $target = "z09az";
      
      my $match = $re->match($target);
      
      unless ($match) {
        return 0;
      }
    }

    # Not Match char class range
    {
      my $re = SPVM::Regex->new("[0-9a-c]+");
      my $target = "zz";
      
      my $match = $re->match($target);
      
      if ($match) {
        return 0;
      }
    }
    
    return 1;
  }
  
  sub match_char_class : int () {

    # Match char class
    {
      my $re = SPVM::Regex->new("[bcdあ]+");
      my $target = "zabcあz";
      
      my $match = $re->match($target);
      
      unless ($match) {
        return 0;
      }
    }

    # Match char class \d
    {
      my $re = SPVM::Regex->new("[\da]+");
      my $target = "z01az";
      
      my $match = $re->match($target);
      
      unless ($match) {
        return 0;
      }
    }

    # Not Match char class
    {
      my $re = SPVM::Regex->new("[bcd\d]+");
      my $target = "ae";
      
      my $match = $re->match($target);
      
      if ($match) {
        return 0;
      }
    }
    
    return 1;
  }

  sub match_not_space : int () {

    # Match not space
    {
      my $re = SPVM::Regex->new("\s+\S+\s+");
      my $target = "\f\tzacz \r\n";
      
      my $match = $re->match($target);
      
      unless ($match) {
        return 0;
      }
    }

    # Not Match not space
    {
      my $re = SPVM::Regex->new("\S+");
      my $target = "\f\t \r\n";
      
      my $match = $re->match($target);
      
      if ($match) {
        return 0;
      }
    }
    
    return 1;
  }
  sub match_space : int () {

    # Match space
    {
      my $re = SPVM::Regex->new("a\s+c");
      my $target = "za\f\t\r\n cz";
      
      my $match = $re->match($target);
      
      unless ($match) {
        return 0;
      }
    }

    # Not Match
    {
      my $re = SPVM::Regex->new("\s+");
      my $target = "\aabc\0";
      
      my $match = $re->match($target);
      
      if ($match) {
        return 0;
      }
    }
    
    return 1;
  }

  sub match_not_word : int () {

    # Match not number
    {
      my $re = SPVM::Regex->new("\w\W+\w");
      my $target = "0-:9";
      
      my $match = $re->match($target);
      
      unless ($match) {
        return 0;
      }
    }
    
    # Match not a-z
    {
      my $re = SPVM::Regex->new("\w\W+\w");
      my $target = "ab`{yz";
      
      my $match = $re->match($target);
      
      unless ($match) {
        return 0;
      }
    }

    # Match not A-Z
    {
      my $re = SPVM::Regex->new("\w\W+\w");
      my $target = "AB`{YZ";
      
      my $match = $re->match($target);
      
      unless ($match) {
        return 0;
      }
    }

    # Match not _
    {
      my $re = SPVM::Regex->new("\w\W+\w");
      my $target = "_^`_";
      
      my $match = $re->match($target);
      
      unless ($match) {
        return 0;
      }
    }

    # not Match 
    {
      my $re = SPVM::Regex->new("\W+");
      my $target = "azAZ_09";
      
      my $match = $re->match($target);
      
      if ($match) {
        return 0;
      }
    }
    
    return 1;
  }

  sub match_word : int () {

    # Match number
    {
      my $re = SPVM::Regex->new("\-\w+\:");
      my $target = "-0123456789:";
      
      my $match = $re->match($target);
      
      unless ($match) {
        return 0;
      }
    }
    
    # Match a-z
    {
      my $re = SPVM::Regex->new("\`\w+\{");
      my $target = "`abyz{";
      
      my $match = $re->match($target);
      
      unless ($match) {
        return 0;
      }
    }

    # Match A-Z
    {
      my $re = SPVM::Regex->new("\`\w+\{");
      my $target = "`ABYZ{";
      
      my $match = $re->match($target);
      
      unless ($match) {
        return 0;
      }
    }

    # Match _
    {
      my $re = SPVM::Regex->new("\^\w+\`");
      my $target = "^__`";
      
      my $match = $re->match($target);
      
      unless ($match) {
        return 0;
      }
    }

    # Match Not
    {
      my $re = SPVM::Regex->new("\w+");
      my $target = "{}あいう";
      
      my $match = $re->match($target);
      
      if ($match) {
        return 0;
      }
    }
    
    return 1;
  }

  sub match_not_number : int () {

    # Match not number
    {
      my $re = SPVM::Regex->new("0\D+9");
      my $target = "0abc9";
      
      my $match = $re->match($target);
      
      unless ($match) {
        return 0;
      }
    }
    
    return 1;
  }

  sub match_number : int () {

    # Match number
    {
      my $re = SPVM::Regex->new("a\d+c");
      my $target = "za0123456789cz";
      
      my $match = $re->match($target);
      
      unless ($match) {
        return 0;
      }
    }
    
    # Match number and not number
    {
      {
        my $re = SPVM::Regex->new("\d+\D+\d+");
        my $target = "123abc789";
        
        my $match = $re->match($target);
        
        unless ($match) {
          return 0;
        }
      }
    }
    
    return 1;
  }
  
  sub invalid_regex : int () {
    # Invalid - Charset after variable quantifier is duplicate
    {
      eval { SPVM::Regex->new("a*a"); };
      unless ($@) {
        return 0;
      }

      eval { SPVM::Regex->new("a?a"); };
      unless ($@) {
        return 0;
      }

      eval { SPVM::Regex->new("a+a"); };
      unless ($@) {
        return 0;
      }
      
      eval { SPVM::Regex->new("a{1,3}a"); };
      unless ($@) {
        return 0;
      }

      eval { SPVM::Regex->new("\d+\D*\d+"); };
      unless ($@) {
        return 0;
      }

      eval { SPVM::Regex->new("\d+\D?\d+"); };
      unless ($@) {
        return 0;
      }
      
      $@ = undef;
    }

    # Valid - aa
    {
       SPVM::Regex->new("aa");
       SPVM::Regex->new("a{3,3}a");
       SPVM::Regex->new("\d\D\d");
    }
    
    return 1;
  }

  sub match_end : int () {
    # Match $
    {
      # Match $ - "zabbc"
      {
        my $re = SPVM::Regex->new("ab+c$");
        my $target = "zabbc";
        
        my $match = $re->match($target);
        
        unless ($match) {
          return 0;
        }
      }
      
      # Not Match $ - "zabbcz"
      {
        my $re = SPVM::Regex->new("ab+c$");
        my $target = "zabbcz";
        
        my $match = $re->match($target);
        
        if ($match) {
          return 0;
        }
      }
    }
    
    return 1;
  }

  sub match_start : int () {
    # Match ^
    {
      # Match ^ - "abbcz"
      {
        my $re = SPVM::Regex->new("^ab+c");
        my $target = "abbcz";
        
        my $match = $re->match($target);
        
        unless ($match) {
          return 0;
        }
      }
      
      # Not Match ^ - "zabbcz"
      {
        my $re = SPVM::Regex->new("^ab+c");
        my $target = "zabbcz";
        
        my $match = $re->match($target);
        
        if ($match) {
          return 0;
        }
      }
    }
    
    return 1;
  }
  
  sub match_quantifier : int () {
    # Match {1,3}
    {
      # Match {1,3} - "zabcz"
      {
        my $re = SPVM::Regex->new("ab{1,3}c");
        my $target = "zabcz";
        
        my $match = $re->match($target);
        
        unless ($match) {
          return 0;
        }
      }
      
      # Match {1,3} - "zabbbcz"
      {
        my $re = SPVM::Regex->new("ab{1,3}c");
        my $target = "zabbbcz";
        
        my $match = $re->match($target);
        
        unless ($match) {
          return 0;
        }
      }

      # Not Match {1,3} - "zacz"
      {
        my $re = SPVM::Regex->new("ab{1,3}c");
        my $target = "zacz";
        
        my $match = $re->match($target);
        
        if ($match) {
          return 0;
        }
      }
      # Not Match {1,3} - "zabbbbcz"
      {
        my $re = SPVM::Regex->new("ab{1,3}c");
        my $target = "zabbbbcz";
        
        my $match = $re->match($target);
        
        if ($match) {
          return 0;
        }
      }
    }

    # Match {11,13}
    {
      # Match {11,13} - "zabbbbbbbbbbbcz"
      {
        my $re = SPVM::Regex->new("ab{11,13}c");
        my $target = "zabbbbbbbbbbbcz";
        
        my $match = $re->match($target);
        
        unless ($match) {
          return 0;
        }
      }
      
      # Match {11,13} - "zabbbcz"
      {
        my $re = SPVM::Regex->new("ab{11,13}c");
        my $target = "zabbbbbbbbbbbbbcz";
        
        my $match = $re->match($target);
        
        unless ($match) {
          return 0;
        }
      }

      # Not Match {11,13} - "zacz"
      {
        my $re = SPVM::Regex->new("ab{11,13}c");
        my $target = "zabbbbbbbbbbcz";
        
        my $match = $re->match($target);
        
        if ($match) {
          return 0;
        }
      }
      # Not Match {11,13} - "zabbbbcz"
      {
        my $re = SPVM::Regex->new("ab{11,13}c");
        my $target = "zabbbbbbbbbbbbbbcz";
        
        my $match = $re->match($target);
        
        if ($match) {
          return 0;
        }
      }
    }
    
    return 1;
  }

  sub match_one_or_zero : int () {
    # Match ?
    {
      # Match ? - "zabcz"
      {
        my $re = SPVM::Regex->new("ab?c");
        my $target = "zabcz";
        
        my $match = $re->match($target);
        
        unless ($match) {
          return 0;
        }
      }

      # Not Match ? - "zabbcz"
      {
        my $re = SPVM::Regex->new("ab?c");
        my $target = "zabbcz";
        
        my $match = $re->match($target);
        
        if ($match) {
          return 0;
        }
      }

      # Match ? - "zacz"
      {
        my $re = SPVM::Regex->new("ab?c");
        my $target = "zacz";
        
        my $match = $re->match($target);
        
        unless ($match) {
          return 0;
        }
      }
    }
    
    return 1;
  }
  
  sub match_one_more : int () {
    # Match +
    {
      # Match + - "zabcz"
      {
        my $re = SPVM::Regex->new("ab+c");
        my $target = "zabcz";
        
        my $match = $re->match($target);
        
        unless ($match) {
          return 0;
        }
      }

      # Match + - "zabbcz"
      {
        my $re = SPVM::Regex->new("ab+c");
        my $target = "zabbcz";
        
        my $match = $re->match($target);
        
        unless ($match) {
          return 0;
        }
      }

      # Not Match + - "zacz"
      {
        my $re = SPVM::Regex->new("ab+c");
        my $target = "zacz";
        
        my $match = $re->match($target);
        
        if ($match) {
          return 0;
        }
      }
    }
    
    return 1;
  }

  sub match_zero_more : int () {
    # Match *
    {
      # Match * - "zabcz"
      {
        my $re = SPVM::Regex->new("ab*c");
        my $target = "zabcz";
        
        my $match = $re->match($target);
        
        unless ($match) {
          return 0;
        }
      }

      # Match * - "zabbcz"
      {
        my $re = SPVM::Regex->new("ab*c");
        my $target = "zabbcz";
        
        my $match = $re->match($target);
        
        unless ($match) {
          return 0;
        }
      }

      # Match * - "zacz"
      {
        my $re = SPVM::Regex->new("ab*c");
        my $target = "zacz";
        
        my $match = $re->match($target);
        
        unless ($match) {
          return 0;
        }
      }

      # Not Match * - "zabbdz"
      {
        my $re = SPVM::Regex->new("ab*c");
        my $target = "zabbdz";
        
        my $match = $re->match($target);
        
        if ($match) {
          return 0;
        }
      }
    }
    
    return 1;
  }

  sub match : int () {

    # Match string
    {
      my $re = SPVM::Regex->new("abc");
      my $target = "zabcz";
      
      my $match = $re->match($target);
      
      unless ($match) {
        return 0;
      }
      
      unless ($match isa string[]) {
        return 0;
      }
      
      unless (@$match == 0) {
        return 0;
      }
    }
    
    # Match same string
    {
      my $re = SPVM::Regex->new("abc");
      my $target = "abc";
      
      my $match = $re->match($target);
      
      unless ($match) {
        return 0;
      }
      
      unless ($match isa string[]) {
        return 0;
      }
      
      unless (@$match == 0) {
        return 0;
      }
    }

    return 1;
  }
}
