/* This file is part of GNUnet Copyright (C) 2012 GNUnet e.V. GNUnet is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . SPDX-License-Identifier: AGPL3.0-or-later */ /** * @file regex/test_regex_proofs.c * @brief test for regex.c * @author Maximilian Szengel */ #include "platform.h" #include "regex_internal_lib.h" #include "regex_test_lib.h" #include "regex_internal.h" /** * Test if the given regex's canonical regex is the same as this canonical * regex's canonical regex. Confused? Ok, then: 1. construct a dfa A from the * given 'regex' 2. get the canonical regex of dfa A 3. construct a dfa B from * this canonical regex 3. compare the canonical regex of dfa A with the * canonical regex of dfa B. * * @param regex regular expression used for this test (see above). * * @return 0 on success, 1 on failure */ static unsigned int test_proof(const char *regex) { unsigned int error; struct REGEX_INTERNAL_Automaton *dfa; char *c_rx1; const char *c_rx2; dfa = REGEX_INTERNAL_construct_dfa(regex, strlen(regex), 1); GNUNET_assert(NULL != dfa); c_rx1 = GNUNET_strdup(REGEX_INTERNAL_get_canonical_regex(dfa)); REGEX_INTERNAL_automaton_destroy(dfa); dfa = REGEX_INTERNAL_construct_dfa(c_rx1, strlen(c_rx1), 1); GNUNET_assert(NULL != dfa); c_rx2 = REGEX_INTERNAL_get_canonical_regex(dfa); error = (0 == strcmp(c_rx1, c_rx2)) ? 0 : 1; if (error > 0) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Comparing canonical regex of\n%s\nfailed:\n%s\nvs.\n%s\n", regex, c_rx1, c_rx2); } GNUNET_free(c_rx1); REGEX_INTERNAL_automaton_destroy(dfa); return error; } /** * Use 'test_proof' function to randomly test the canonical regexes of 'count' * random expressions of length 'rx_length'. * * @param count number of random regular expressions to test. * @param rx_length length of the random regular expressions. * * @return 0 on succes, number of failures otherwise. */ static unsigned int test_proofs_random(unsigned int count, size_t rx_length) { unsigned int i; char *rand_rx; unsigned int failures; failures = 0; for (i = 0; i < count; i++) { rand_rx = REGEX_TEST_generate_random_regex(rx_length, NULL); failures += test_proof(rand_rx); GNUNET_free(rand_rx); } return failures; } /** * Test a number of known examples of regexes for proper canonicalization. * * @return 0 on success, number of failures otherwise. */ static unsigned int test_proofs_static() { unsigned int i; unsigned int error; const char *regex[8] = { "a|aa*a", "a+", "a*", "a*a*", "(F*C|WfPf|y+F*C)", "y*F*C|WfPf", "((a|b)c|(a|b)(d|(a|b)e))", "((a|b)(c|d)|(a|b)(a|b)e)" }; const char *canon_rx1; const char *canon_rx2; struct REGEX_INTERNAL_Automaton *dfa1; struct REGEX_INTERNAL_Automaton *dfa2; error = 0; for (i = 0; i < 8; i += 2) { dfa1 = REGEX_INTERNAL_construct_dfa(regex[i], strlen(regex[i]), 1); dfa2 = REGEX_INTERNAL_construct_dfa(regex[i + 1], strlen(regex[i + 1]), 1); GNUNET_assert(NULL != dfa1); GNUNET_assert(NULL != dfa2); canon_rx1 = REGEX_INTERNAL_get_canonical_regex(dfa1); canon_rx2 = REGEX_INTERNAL_get_canonical_regex(dfa2); error += (0 == strcmp(canon_rx1, canon_rx2)) ? 0 : 1; if (error > 0) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Comparing canonical regex failed:\nrx1:\t%s\ncrx1:\t%s\nrx2:\t%s\ncrx2:\t%s\n", regex[i], canon_rx1, regex[i + 1], canon_rx2); } REGEX_INTERNAL_automaton_destroy(dfa1); REGEX_INTERNAL_automaton_destroy(dfa2); } return error; } int main(int argc, char *argv[]) { GNUNET_log_setup("test-regex", "WARNING", NULL); int error; error = 0; error += test_proofs_static(); error += test_proofs_random(100, 30); return error; }