| | #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(); |
| | } |