| #include "../../unity/unity.h" |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdbool.h> |
| #include <unistd.h> |
| #include <sys/wait.h> |
| #include <fcntl.h> |
| #include <errno.h> |
|
|
| |
| |
|
|
| |
| |
| |
|
|
| |
| |
| static int run_parse_patterns_in_child(int argc, int start, char **argv, |
| char *errbuf, size_t errbufsz) |
| { |
| int pipefd[2]; |
| if (pipe(pipefd) != 0) |
| return -1; |
|
|
| fflush(stdout); |
| fflush(stderr); |
| pid_t pid = fork(); |
| if (pid < 0) |
| { |
| close(pipefd[0]); |
| close(pipefd[1]); |
| return -1; |
| } |
|
|
| if (pid == 0) |
| { |
| |
| (void)dup2(pipefd[1], STDERR_FILENO); |
| close(pipefd[0]); |
| close(pipefd[1]); |
|
|
| |
| |
| extern idx_t control_used; |
| extern char **global_argv; |
| control_used = 0; |
| global_argv = argv; |
|
|
| |
| parse_patterns(argc, start, argv); |
| _exit(0); |
| } |
|
|
| |
| close(pipefd[1]); |
| ssize_t total = 0; |
| while (total < (ssize_t)errbufsz - 1) |
| { |
| ssize_t n = read(pipefd[0], errbuf + total, errbufsz - 1 - total); |
| if (n > 0) |
| total += n; |
| else |
| break; |
| } |
| errbuf[total] = '\0'; |
| close(pipefd[0]); |
|
|
| int status = 0; |
| if (waitpid(pid, &status, 0) < 0) |
| return -1; |
|
|
| if (WIFEXITED(status)) |
| return WEXITSTATUS(status); |
| else if (WIFSIGNALED(status)) |
| return 128 + WTERMSIG(status); |
| else |
| return -1; |
| } |
|
|
| void setUp(void) { |
| |
| extern idx_t control_used; |
| control_used = 0; |
|
|
| |
| |
| extern char **global_argv; |
| global_argv = NULL; |
| } |
|
|
| void tearDown(void) { |
| |
| } |
|
|
| |
| void test_parse_patterns_regexp_with_offset_and_ignore(void) |
| { |
| extern struct control *controls; |
| extern idx_t control_used; |
| extern char **global_argv; |
|
|
| char *argv[] = { "/foo/", "%bar%+3" }; |
| int argc = 2; |
| int start = 0; |
| global_argv = argv; |
|
|
| parse_patterns(argc, start, argv); |
|
|
| TEST_ASSERT_EQUAL_INT64(2, control_used); |
|
|
| |
| TEST_ASSERT_TRUE(controls[0].regexpr); |
| TEST_ASSERT_FALSE(controls[0].ignore); |
| TEST_ASSERT_EQUAL_INT(0, controls[0].offset); |
| TEST_ASSERT_EQUAL_INT(0, controls[0].argnum); |
|
|
| |
| TEST_ASSERT_TRUE(controls[1].regexpr); |
| TEST_ASSERT_TRUE(controls[1].ignore); |
| TEST_ASSERT_EQUAL_INT(3, controls[1].offset); |
| TEST_ASSERT_EQUAL_INT(1, controls[1].argnum); |
| } |
|
|
| |
| void test_parse_patterns_numeric_with_repeat_integer(void) |
| { |
| extern struct control *controls; |
| extern idx_t control_used; |
| extern char **global_argv; |
|
|
| char rep[] = "{3}"; |
| char *argv[] = { "5", rep }; |
| int argc = 2; |
| int start = 0; |
| global_argv = argv; |
|
|
| parse_patterns(argc, start, argv); |
|
|
| TEST_ASSERT_EQUAL_INT64(1, control_used); |
| TEST_ASSERT_FALSE(controls[0].regexpr); |
| TEST_ASSERT_EQUAL_INT64(5, controls[0].lines_required); |
| TEST_ASSERT_FALSE(controls[0].repeat_forever); |
| TEST_ASSERT_EQUAL_INT64(3, controls[0].repeat); |
| } |
|
|
| |
| void test_parse_patterns_repeat_star(void) |
| { |
| extern struct control *controls; |
| extern idx_t control_used; |
| extern char **global_argv; |
|
|
| char rep[] = "{*}"; |
| char *argv[] = { "6", rep }; |
| int argc = 2; |
| int start = 0; |
| global_argv = argv; |
|
|
| parse_patterns(argc, start, argv); |
|
|
| TEST_ASSERT_EQUAL_INT64(1, control_used); |
| TEST_ASSERT_FALSE(controls[0].regexpr); |
| TEST_ASSERT_EQUAL_INT64(6, controls[0].lines_required); |
| TEST_ASSERT_TRUE(controls[0].repeat_forever); |
| } |
|
|
| |
| void test_parse_patterns_equal_line_ok_warning(void) |
| { |
| extern struct control *controls; |
| extern idx_t control_used; |
| extern char **global_argv; |
|
|
| char *argv[] = { "6" }; |
| int argc = 1; |
| int start = 0; |
| global_argv = argv; |
|
|
| parse_patterns(argc, start, argv); |
|
|
| TEST_ASSERT_EQUAL_INT64(1, control_used); |
| TEST_ASSERT_FALSE(controls[0].regexpr); |
| TEST_ASSERT_EQUAL_INT64(6, controls[0].lines_required); |
| } |
|
|
| |
| void test_parse_patterns_argnum_indices(void) |
| { |
| extern struct control *controls; |
| extern idx_t control_used; |
| extern char **global_argv; |
|
|
| char *argv[] = { "FILE", "IGNORED", "/x/", "10" }; |
| int argc = 4; |
| int start = 2; |
| global_argv = argv; |
|
|
| parse_patterns(argc, start, argv); |
|
|
| TEST_ASSERT_EQUAL_INT64(2, control_used); |
| TEST_ASSERT_TRUE(controls[0].regexpr); |
| TEST_ASSERT_EQUAL_INT(2, controls[0].argnum); |
|
|
| TEST_ASSERT_FALSE(controls[1].regexpr); |
| TEST_ASSERT_EQUAL_INT(3, controls[1].argnum); |
| TEST_ASSERT_EQUAL_INT64(10, controls[1].lines_required); |
| } |
|
|
| |
| void test_parse_patterns_regex_with_repeat_integer(void) |
| { |
| extern struct control *controls; |
| extern idx_t control_used; |
| extern char **global_argv; |
|
|
| char rep[] = "{2}"; |
| char *argv[] = { "/baz/", rep }; |
| int argc = 2; |
| int start = 0; |
| global_argv = argv; |
|
|
| parse_patterns(argc, start, argv); |
|
|
| TEST_ASSERT_EQUAL_INT64(1, control_used); |
| TEST_ASSERT_TRUE(controls[0].regexpr); |
| TEST_ASSERT_FALSE(controls[0].repeat_forever); |
| TEST_ASSERT_EQUAL_INT64(2, controls[0].repeat); |
| } |
|
|
| |
| void test_parse_patterns_zero_line_error(void) |
| { |
| char *argv[] = { "0" }; |
| char errbuf[1024]; |
| int status = run_parse_patterns_in_child(1, 0, argv, errbuf, sizeof errbuf); |
| TEST_ASSERT_NOT_EQUAL(0, status); |
| } |
|
|
| |
| void test_parse_patterns_decreasing_line_error(void) |
| { |
| char *argv[] = { "5", "3" }; |
| char errbuf[1024]; |
| int status = run_parse_patterns_in_child(2, 0, argv, errbuf, sizeof errbuf); |
| TEST_ASSERT_NOT_EQUAL(0, status); |
| } |
|
|
| |
| void test_parse_patterns_invalid_pattern_non_number_error(void) |
| { |
| char *argv[] = { "abc" }; |
| char errbuf[1024]; |
| int status = run_parse_patterns_in_child(1, 0, argv, errbuf, sizeof errbuf); |
| TEST_ASSERT_NOT_EQUAL(0, status); |
| } |
|
|
| |
| void test_parse_patterns_missing_closing_delimiter_error(void) |
| { |
| char *argv[] = { "/abc" }; |
| char errbuf[1024]; |
| int status = run_parse_patterns_in_child(1, 0, argv, errbuf, sizeof errbuf); |
| TEST_ASSERT_NOT_EQUAL(0, status); |
| } |
|
|
| |
| void test_parse_patterns_invalid_regex_error(void) |
| { |
| char *argv[] = { "/[/" }; |
| char errbuf[1024]; |
| int status = run_parse_patterns_in_child(1, 0, argv, errbuf, sizeof errbuf); |
| TEST_ASSERT_NOT_EQUAL(0, status); |
| } |
|
|
| |
| void test_parse_patterns_repeat_missing_right_brace_error(void) |
| { |
| |
| char badrep[] = "{3"; |
| char *argv[] = { "1", badrep }; |
| char errbuf[1024]; |
| int status = run_parse_patterns_in_child(2, 0, argv, errbuf, sizeof errbuf); |
| TEST_ASSERT_NOT_EQUAL(0, status); |
| } |
|
|
| int main(void) |
| { |
| UNITY_BEGIN(); |
|
|
| RUN_TEST(test_parse_patterns_regexp_with_offset_and_ignore); |
| RUN_TEST(test_parse_patterns_numeric_with_repeat_integer); |
| RUN_TEST(test_parse_patterns_repeat_star); |
| RUN_TEST(test_parse_patterns_equal_line_ok_warning); |
| RUN_TEST(test_parse_patterns_argnum_indices); |
| RUN_TEST(test_parse_patterns_regex_with_repeat_integer); |
|
|
| RUN_TEST(test_parse_patterns_zero_line_error); |
| RUN_TEST(test_parse_patterns_decreasing_line_error); |
| RUN_TEST(test_parse_patterns_invalid_pattern_non_number_error); |
| RUN_TEST(test_parse_patterns_missing_closing_delimiter_error); |
| RUN_TEST(test_parse_patterns_invalid_regex_error); |
| RUN_TEST(test_parse_patterns_repeat_missing_right_brace_error); |
|
|
| return UNITY_END(); |
| } |