pcre2 / tests /tests_pcre2_compile_read_repeat_counts.c
AryaWu's picture
Upload folder using huggingface_hub
864071c verified
#include "unity/unity.h"
#define PCRE2_CODE_UNIT_WIDTH 8
#include "pcre2.h"
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
/* Wrapper provided in the module under test */
extern BOOL test_read_repeat_counts(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend,
uint32_t *minp, uint32_t *maxp,
int *errorcodeptr);
static BOOL call_rrc(const char *s, uint32_t *minp, uint32_t *maxp, int *errp, PCRE2_SPTR *pvar_out, PCRE2_SPTR *pend_out)
{
/* The function expects ptrptr to point to the char after '{' */
TEST_ASSERT_NOT_NULL(s);
const char *open = strchr(s, '{');
TEST_ASSERT_NOT_NULL_MESSAGE(open, "Test pattern must contain '{'");
PCRE2_SPTR p = (PCRE2_SPTR)(open + 1);
PCRE2_SPTR pend = (PCRE2_SPTR)(s + strlen(s));
BOOL rc = test_read_repeat_counts(&p, pend, minp, maxp, errp);
if (pvar_out) *pvar_out = p;
if (pend_out) *pend_out = pend;
return rc;
}
void setUp(void) { }
void tearDown(void) { }
/* {n} */
void test_read_repeat_counts_exact_n(void)
{
const char *pat = "{5}";
uint32_t minv = 0, maxv = 0;
int err = -1;
PCRE2_SPTR p_after = NULL;
BOOL ok = call_rrc(pat, &minv, &maxv, &err, &p_after, NULL);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_INT(0, err);
TEST_ASSERT_EQUAL_UINT32(5u, minv);
TEST_ASSERT_EQUAL_UINT32(5u, maxv);
const char *close = strchr(pat, '}');
TEST_ASSERT_NOT_NULL(close);
TEST_ASSERT_EQUAL_PTR(close + 1, p_after);
}
/* {n,m} */
void test_read_repeat_counts_n_m(void)
{
const char *pat = "{2,4}";
uint32_t minv = 0, maxv = 0;
int err = -1;
PCRE2_SPTR p_after = NULL;
BOOL ok = call_rrc(pat, &minv, &maxv, &err, &p_after, NULL);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_INT(0, err);
TEST_ASSERT_EQUAL_UINT32(2u, minv);
TEST_ASSERT_EQUAL_UINT32(4u, maxv);
const char *close = strchr(pat, '}');
TEST_ASSERT_EQUAL_PTR(close + 1, p_after);
}
/* {n,} - unlimited upper bound (we don't assert exact max, just success and min) */
void test_read_repeat_counts_n_unlimited(void)
{
const char *pat = "{7,}";
uint32_t minv = 0, maxv = 0;
int err = -1;
PCRE2_SPTR p_after = NULL;
BOOL ok = call_rrc(pat, &minv, &maxv, &err, &p_after, NULL);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_INT(0, err);
TEST_ASSERT_EQUAL_UINT32(7u, minv);
/* maxv is some internal "unlimited" value; do not assert exact value */
TEST_ASSERT_TRUE(maxv >= minv);
const char *close = strchr(pat, '}');
TEST_ASSERT_EQUAL_PTR(close + 1, p_after);
}
/* {,m} */
void test_read_repeat_counts_unbounded_m(void)
{
const char *pat = "{,9}";
uint32_t minv = 12345, maxv = 12345;
int err = -1;
PCRE2_SPTR p_after = NULL;
BOOL ok = call_rrc(pat, &minv, &maxv, &err, &p_after, NULL);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_INT(0, err);
TEST_ASSERT_EQUAL_UINT32(0u, minv);
TEST_ASSERT_EQUAL_UINT32(9u, maxv);
const char *close = strchr(pat, '}');
TEST_ASSERT_EQUAL_PTR(close + 1, p_after);
}
/* Whitespace: "{ \t3 \t , \t 6 \t }" */
void test_read_repeat_counts_whitespace(void)
{
const char *pat = "{ \t3 \t , \t 6 \t }";
uint32_t minv = 0, maxv = 0;
int err = -1;
PCRE2_SPTR p_after = NULL;
BOOL ok = call_rrc(pat, &minv, &maxv, &err, &p_after, NULL);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_INT(0, err);
TEST_ASSERT_EQUAL_UINT32(3u, minv);
TEST_ASSERT_EQUAL_UINT32(6u, maxv);
const char *close = strrchr(pat, '}');
TEST_ASSERT_EQUAL_PTR(close + 1, p_after);
}
/* Not a quantifier: "{,}" -> FALSE, no error, pointer unchanged */
void test_read_repeat_counts_not_quantifier_returns_false_no_error(void)
{
const char *pat = "{,}";
uint32_t minv = 111, maxv = 222;
int err = -1;
PCRE2_SPTR p_initial = NULL, p_after = NULL, pend = NULL;
/* Compute initial pointer (after '{') */
const char *open = strchr(pat, '{');
TEST_ASSERT_NOT_NULL(open);
p_initial = (PCRE2_SPTR)(open + 1);
(void)test_read_repeat_counts(&p_initial, (PCRE2_SPTR)(pat + strlen(pat)), &minv, &maxv, &err);
/* Re-run using helper to get behavior check */
err = -1; minv = 0; maxv = 0;
BOOL ok = call_rrc(pat, &minv, &maxv, &err, &p_after, &pend);
TEST_ASSERT_FALSE(ok);
TEST_ASSERT_EQUAL_INT(0, err);
/* Pointer unchanged (still points to the char after '{') */
TEST_ASSERT_EQUAL_PTR(open + 1, p_after);
}
/* Invalid order: "{5,3}" -> FALSE, error set (max < min) */
void test_read_repeat_counts_invalid_order_sets_error(void)
{
const char *pat = "{5,3}";
uint32_t minv = 0, maxv = 0;
int err = 0;
BOOL ok = call_rrc(pat, &minv, &maxv, &err, NULL, NULL);
TEST_ASSERT_FALSE(ok);
TEST_ASSERT_NOT_EQUAL(0, err); /* Some error code must be set */
}
/* Overlarge min: "{70000}" -> FALSE, error set */
void test_read_repeat_counts_overlarge_min_sets_error(void)
{
const char *pat = "{70000}";
uint32_t minv = 0, maxv = 0;
int err = 0;
BOOL ok = call_rrc(pat, &minv, &maxv, &err, NULL, NULL);
TEST_ASSERT_FALSE(ok);
TEST_ASSERT_NOT_EQUAL(0, err);
}
/* Overlarge max: "{1,70000}" -> FALSE, error set */
void test_read_repeat_counts_overlarge_max_sets_error(void)
{
const char *pat = "{1,70000}";
uint32_t minv = 0, maxv = 0;
int err = 0;
BOOL ok = call_rrc(pat, &minv, &maxv, &err, NULL, NULL);
TEST_ASSERT_FALSE(ok);
TEST_ASSERT_NOT_EQUAL(0, err);
}
/* Missing closing brace: "{3,4" -> FALSE, no error; pointer unchanged */
void test_read_repeat_counts_missing_closing_brace_returns_false(void)
{
const char *pat = "{3,4";
uint32_t minv = 0, maxv = 0;
int err = -1;
PCRE2_SPTR p_after = NULL;
BOOL ok = call_rrc(pat, &minv, &maxv, &err, &p_after, NULL);
TEST_ASSERT_FALSE(ok);
TEST_ASSERT_EQUAL_INT(0, err);
const char *open = strchr(pat, '{');
TEST_ASSERT_EQUAL_PTR(open + 1, p_after);
}
/* Pointer should stop right after the '}' even with trailing text */
void test_read_repeat_counts_pointer_advances_to_after_brace(void)
{
const char *pat = "{2,3}ABC";
uint32_t minv = 0, maxv = 0;
int err = -1;
PCRE2_SPTR p_after = NULL;
BOOL ok = call_rrc(pat, &minv, &maxv, &err, &p_after, NULL);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_INT(0, err);
const char *close = strchr(pat, '}');
TEST_ASSERT_EQUAL_PTR(close + 1, p_after);
}
/* {0,} and {,0} are valid edge cases */
void test_read_repeat_counts_zero_bounds(void)
{
const char *pat1 = "{0,}";
const char *pat2 = "{,0}";
uint32_t minv = 123, maxv = 456;
int err = -1;
BOOL ok1 = call_rrc(pat1, &minv, &maxv, &err, NULL, NULL);
TEST_ASSERT_TRUE(ok1);
TEST_ASSERT_EQUAL_INT(0, err);
TEST_ASSERT_EQUAL_UINT32(0u, minv);
err = -1; minv = 123; maxv = 456;
BOOL ok2 = call_rrc(pat2, &minv, &maxv, &err, NULL, NULL);
TEST_ASSERT_TRUE(ok2);
TEST_ASSERT_EQUAL_INT(0, err);
TEST_ASSERT_EQUAL_UINT32(0u, minv);
TEST_ASSERT_EQUAL_UINT32(0u, maxv);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_read_repeat_counts_exact_n);
RUN_TEST(test_read_repeat_counts_n_m);
RUN_TEST(test_read_repeat_counts_n_unlimited);
RUN_TEST(test_read_repeat_counts_unbounded_m);
RUN_TEST(test_read_repeat_counts_whitespace);
RUN_TEST(test_read_repeat_counts_not_quantifier_returns_false_no_error);
RUN_TEST(test_read_repeat_counts_invalid_order_sets_error);
RUN_TEST(test_read_repeat_counts_overlarge_min_sets_error);
RUN_TEST(test_read_repeat_counts_overlarge_max_sets_error);
RUN_TEST(test_read_repeat_counts_missing_closing_brace_returns_false);
RUN_TEST(test_read_repeat_counts_pointer_advances_to_after_brace);
RUN_TEST(test_read_repeat_counts_zero_bounds);
return UNITY_END();
}