diff options
author | Maximilian Szengel <gnunet@maxsz.de> | 2012-04-05 11:46:24 +0000 |
---|---|---|
committer | Maximilian Szengel <gnunet@maxsz.de> | 2012-04-05 11:46:24 +0000 |
commit | 4bddef66e721cf68b17effea2c23aebd89ca1b8b (patch) | |
tree | 151e1e4ccdee93d60d5fbc99108a7e4eb88fe0d2 /src/regex/test_regex.c | |
parent | ff1407f3502c2294dbf9f2c6a753b9e3fa04973a (diff) |
Automatic regex generation for testing
Diffstat (limited to 'src/regex/test_regex.c')
-rw-r--r-- | src/regex/test_regex.c | 215 |
1 files changed, 178 insertions, 37 deletions
diff --git a/src/regex/test_regex.c b/src/regex/test_regex.c index 7428c001e4..d32bc9ed8f 100644 --- a/src/regex/test_regex.c +++ b/src/regex/test_regex.c @@ -23,7 +23,7 @@ * @author Maximilian Szengel */ #include <regex.h> - +#include <time.h> #include "platform.h" #include "gnunet_regex_lib.h" @@ -36,44 +36,164 @@ enum Match_Result struct Regex_String_Pair { char *regex; - char *string; - enum Match_Result expected_result; + int string_count; + char **strings; + enum Match_Result *expected_results; }; - int -test_automaton (struct GNUNET_REGEX_Automaton *a, struct Regex_String_Pair *rxstr) +test_random (unsigned int rx_length, unsigned int max_str_len, unsigned int str_count) { + int i; + int rx_exp; + char rand_rx[rx_length+1]; + char matching_str[str_count][max_str_len+1]; + char *rand_rxp; + char *matching_strp; + int char_op_switch; + int last_was_op; + char current_char; + int eval; + int eval_check; + struct GNUNET_REGEX_Automaton *dfa; regex_t rx; + regmatch_t matchptr[1]; + int char_offset; + char error[200]; + int result; + + // At least one string is needed for matching + GNUNET_assert (str_count > 0); + // The string should be at least as long as the regex itself + GNUNET_assert (max_str_len >= rx_length); + + rand_rxp = rand_rx; + matching_strp = matching_str[0]; + + // Generate random regex and a string that matches the regex + for (i=0; i<rx_length; i++) + { + char_op_switch = 0 + (int)(1.0 * rand() / (RAND_MAX + 1.0)); + char_offset = (rand()%2) ? 65 : 97; + + if (0 == char_op_switch + && !last_was_op) + { + last_was_op = 1; + rx_exp = rand () % 3; + + switch (rx_exp) + { + case 0: + current_char = '+'; + break; + case 1: + current_char = '*'; + break; + case 2: + if (i < rx_length -1) + current_char = '|'; + else + current_char = (char)(char_offset + (int)( 25.0 * rand() / (RAND_MAX + 1.0))); + break; + } + } + else + { + current_char = (char)(char_offset + (int)( 25.0 * rand() / (RAND_MAX + 1.0))); + last_was_op = 0; + } + + if (current_char != '+' + && current_char != '*' + && current_char != '|') + { + *matching_strp = current_char; + matching_strp++; + } + + *rand_rxp = current_char; + rand_rxp++; + } + *rand_rxp = '\0'; + *matching_strp = '\0'; + + result = 0; + + for (i=0; i<str_count; i++) + { + // Match string using DFA + dfa = GNUNET_REGEX_construct_dfa (rand_rx, strlen (rand_rx)); + if (NULL == dfa) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Constructing DFA failed\n"); + return -1; + } + + eval = GNUNET_REGEX_eval (dfa, matching_str[i]); + GNUNET_REGEX_automaton_destroy (dfa); + + // Match string using glibc regex + if (0 != regcomp (&rx, rand_rx, REG_EXTENDED)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not compile regex using regcomp\n"); + return -1; + } + + eval_check = regexec (&rx, matching_str[i], 1, matchptr, 0); + + // We only want to match the whole string, because that's what our DFA does, too. + if (eval_check == 0 && (matchptr[0].rm_so != 0 || matchptr[0].rm_eo != strlen (matching_str[i]))) + eval_check = 1; + + // compare result + if (eval_check != eval) + { + regerror (eval_check, &rx, error, sizeof error); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected result:\nregex: %s\nstring: %s\ngnunet regex: %i\nglibc regex: %i\nglibc error: %s\n\n", + rand_rx, matching_str, eval, eval_check, error); + result += 1; + } + } + return result; +} + +int +test_automaton (struct GNUNET_REGEX_Automaton *a, regex_t *rx, struct Regex_String_Pair *rxstr) +{ int result; int eval; int eval_check; + char error[200]; + int i; if (NULL == a) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Automaton was NULL\n"); return 1; + } result = 0; - eval = GNUNET_REGEX_eval (a, rxstr->string); - regcomp (&rx, rxstr->regex, REG_EXTENDED); - eval_check = regexec (&rx, rxstr->string, 0, NULL, 0); - - if ((rxstr->expected_result == match - && (0 != eval || 0 != eval_check)) - || - (rxstr->expected_result == nomatch - && (0 == eval || 0 == eval_check))) + for (i=0; i<rxstr->string_count; i++) { - result = 1; - char error[200]; - regerror (eval_check, &rx, error, sizeof error); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected result:\nregex: %s\nstring: %s\nexpected result: %i\ngnunet regex: %i\nglibc regex: %i\nglibc error: %s\n\n", - rxstr->regex, rxstr->string, rxstr->expected_result, eval, eval_check, error); - } - - regfree (&rx); + eval = GNUNET_REGEX_eval (a, rxstr->strings[i]); + eval_check = regexec (rx, rxstr->strings[i], 0, NULL, 0); + if ((rxstr->expected_results[i] == match + && (0 != eval || 0 != eval_check)) + || + (rxstr->expected_results[i] == nomatch + && (0 == eval || 0 == eval_check))) + { + result = 1; + regerror (eval_check, rx, error, sizeof error); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected result:\nregex: %s\nstring: %s\nexpected result: %i\ngnunet regex: %i\nglibc regex: %i\nglibc error: %s\n\n", + rxstr->regex, rxstr->strings[i], rxstr->expected_results[i], eval, eval_check, error); + } + } return result; } @@ -90,34 +210,55 @@ main (int argc, char *argv[]) int check_nfa; int check_dfa; + int check_rand; struct Regex_String_Pair rxstr[3]; struct GNUNET_REGEX_Automaton *a; + regex_t rx; int i; - rxstr[0].regex = "ab(c|d)+c*(a(b|c)d)+"; - rxstr[0].string = "abcdcdcdcdddddabd"; - rxstr[0].expected_result = match; + check_nfa = 0; + check_dfa = 0; + check_rand = 0; - rxstr[1].regex = "a*"; - rxstr[1].string = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - rxstr[1].expected_result = match; - - rxstr[2].regex = "a*b*c*d+"; - rxstr[2].string = "a"; - rxstr[2].expected_result = nomatch; + rxstr[0].regex = "ab(c|d)+c*(a(b|c)d)+"; + rxstr[0].string_count = 5; + rxstr[0].strings = GNUNET_malloc (sizeof (char *) * rxstr[0].string_count); + rxstr[0].strings[0] = "abcdcdcdcdddddabd"; + rxstr[0].strings[1] = "abcd"; + rxstr[0].strings[2] = "abcddddddccccccccccccccccccccccccabdacdabd"; + rxstr[0].strings[3] = "abccccca"; + rxstr[0].strings[4] = "abcdcdcdccdabdabd"; + rxstr[0].expected_results = GNUNET_malloc (sizeof (enum Match_Result) * rxstr[0].string_count); + rxstr[0].expected_results[0] = match; + rxstr[0].expected_results[1] = nomatch; + rxstr[0].expected_results[2] = match; + rxstr[0].expected_results[3] = nomatch; + rxstr[0].expected_results[4] = match; - for (i=0; i<3; i++) + for (i=0; i<1; i++) { + if (0 != regcomp (&rx, rxstr->regex, REG_EXTENDED | REG_NOSUB)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not compile regex using regcomp()\n"); + return 1; + } + // NFA test a = GNUNET_REGEX_construct_nfa (rxstr[i].regex, strlen (rxstr[i].regex)); - check_nfa += test_automaton (a, &rxstr[i]); + check_nfa += test_automaton (a, &rx, &rxstr[i]); GNUNET_REGEX_automaton_destroy (a); // DFA test a = GNUNET_REGEX_construct_dfa (rxstr[i].regex, strlen (rxstr[i].regex)); - check_dfa += test_automaton (a, &rxstr[i]); + check_dfa += test_automaton (a, &rx, &rxstr[i]); GNUNET_REGEX_automaton_destroy (a); + + regfree (&rx); } - return check_nfa + check_dfa; + srand (time(NULL)); + for (i=0; i< 100; i++) + check_rand += test_random (100, 100, 1); + + return check_nfa + check_dfa + check_rand; } |