/*

  t-regex.c

  Author: Antti Huima <huima@ssh.fi>

  Copyright (c) 1999 SSH Communications Security, Finland
  All rights reserved.

  Created Tue Sep  7 12:52:02 1999.

  */

#include "sshincludes.h"
#include "sshdebug.h"
#include "sshregex.h"
#include "sshregression.h"

typedef struct {
  const char *regex;
  const char *text;
  const char *first_submatch;
} SshRegexTestItem;

static SshRegexTestItem tests[] =
{ 
  { "Literal match" },
  { "(abcdef)", "abcdefghijklmn", "abcdef" },
  { "(abcdef)", "123456789abcdefghijklmn", "abcdef" },
  { "(abcdef)", "123012301230123abcdef", "abcdef" },
  { "(abcdef)", "123012301230123abcdex", NULL },

  { "Single-level repetition" },
  { "(a*(goo)b*)", "12345678aaaagoobbbb", "aaaagoobbbb" },
  { "foo({bar}*)", "viuvaufoobarbarbar", "barbarbar" },
  { "(a+b+c+)", "zzzaaabbbbcc", "aaabbbbcc" },
  { "(a+b+c+)", "zzzaaaqqqqcc", NULL },
  { "(aa+b+c+)", "zzzabbbcc", NULL },
  { "(aa+b+c+)", "zzzaabbbcc", "aabbbcc" },

  { "Multiple repetitions" },
  { "(a(b(c+))+)", "abccccbcbccc", "abccccbcbccc" },
  { "(a(b(c+))+)", "abccccbbcc", "abcccc" },  
  { "(a(b(c+))+)", "accccbbcc", NULL },  

  { "Bounded repetitions" }, 
  { "a(a/3,5/)", "bbbaaaaaaaa", "aaaaa" },
  { "a(a/3,/)", "bbbaaaaaaaa", "aaaaaaa" },
  { "a(a/0,5/)", "bbbaaaaaaaa", "aaaaa" },
  { "a(a/,3/)", "bbbaaaaaaaa", "aaa" },
  { "a(a/3/)", "bbbaaaaaaaa", "aaa" },

  { "Lazy operators" },
  { "a(a/3,5/?)", "bbbaaaaaaaa", "aaa" },
  { "foo({bar}+?)", "foobarbarbar", "bar" },
  { "foo({bar}+?)x", "foobarbarbarx", "barbarbar" },
  { "(viua*?)", "xxviuaaaa", "viu" },
  { "(viua*?)$", "xxviuaaaa", "viuaaaa" },

  { "Anchoring" },
  { "(.foo)$", "1foo2foo3foo", "3foo" },

  { "Disjunctions" },
  { "(apple|pie|banana)", "I like a banana", "banana" },
  { "(apple|pie|banana)", "I like an apple", "apple" },
  { "(fi|firs|first)", "I am first", "fi" },
  { "(first|firs|fi)", "I am first", "first" },
  { "({a|b}+)", "zop abababba", "abababba" },
  { "({a|foo}+)", "xxxfooafooaaafooa", "fooafooaaafooa" },

  { "Character sets" },
  { "([a:z]+)", "GGabcdefg", "abcdefg" },
  { "([a:z-d]+)", "GGabcdefg", "abc" },
  { "([-x]+)", "abcdefxhi", "abcdef" },
  { "([~d-4]+)", "aaa1234567", "123" },
  { "([-~d]+)", "123456foobar123456", "foobar" },
  { "(~w+)", "       what is this     ", "what" },
  
  { "Boundaries" },
  { "(~<foo.*)", "viufoo barfoo foobar", "foobar" },
  { "(~<[a:z]+foo~>)", "asdfasdffoozz viufoo", "viufoo" },
  { "(~bfoo[a:z]~b)", "goofoo foobaz fooq fooxxx", "fooq" },

};


#define NUM_TESTS ((sizeof(tests) / sizeof(tests[0])))

Boolean do_check(SshRegexContext c, SshRegexTestItem *t)
{
  SshRegexMatcher m;
  int from;
  int len;
  Boolean passed = FALSE;

  m = ssh_regex_create(c, t->regex, SSH_REGEX_SYNTAX_SSH);

  if (m == NULL)
    {
      fprintf(stderr, "(compile error) ");
      return FALSE;
    }

  if (ssh_regex_match_cstr(m, t->text))
    {
      if (t->first_submatch != NULL)
        {
          if (ssh_regex_access_submatch(m, 1, &from, &len))
            {
              if (len == strlen(t->first_submatch) &&
                  !(strncmp(t->first_submatch, t->text + from, len)))
                {
                  passed = TRUE;
                }
            }
        }
    }
  else
    {
      if (t->first_submatch == NULL)
        passed = TRUE;
    }
  ssh_regex_free(m);
  return passed;
}

int main(int argc, char **argv)
{
  int i;
  SshRegexTestItem *t;
  SshRegexContext c;

  ssh_regression_init(&argc, &argv, "Regular expression utility",
                      "huima@ssh.fi");

  c = ssh_regex_create_context();
  
  for (i = 0; i < NUM_TESTS; i++)
    {
      t = &tests[i];
      if (t->text == NULL) 
        {
          ssh_regression_section(t->regex);
          continue;
        }
      SSH_REGRESSION_TEST(t->regex, do_check, (c, t));
    }
  
  ssh_regression_finish();
  return 0;
}
