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