pcre2 / tests /tests_pcre2_compile_class_compile_class_juxtaposition.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 <stdlib.h>
/* We need internal compile structures/constants (eclass_op_info, META_*, ECL_*). */
#include "pcre2_compile.h"
/* eclass_context is defined privately in the module; forward-declare an
incomplete type to declare the test wrapper prototype. We never dereference
it and pass NULL. */
typedef struct eclass_context eclass_context;
/* Test wrapper provided by the module under test. */
extern BOOL test_compile_class_juxtaposition(eclass_context *context, BOOL negated,
uint32_t **pptr, PCRE2_UCHAR **pcode,
eclass_op_info *pop_info,
PCRE2_SIZE *lengthptr);
static int classbits_all_ones(const eclass_op_info *oi)
{
for (int i = 0; i < 8; i++) {
if (oi->bits.classwords[i] != 0xffffffffu) return 0;
}
return 1;
}
static int classbits_all_zeros(const eclass_op_info *oi)
{
for (int i = 0; i < 8; i++) {
if (oi->bits.classwords[i] != 0u) return 0;
}
return 1;
}
void setUp(void) {
/* nothing */
}
void tearDown(void) {
/* nothing */
}
/* Single operand: META_CLASS_EMPTY (non-negated): should yield ECL_NONE with zero bits. */
void test_compile_class_juxtaposition_single_empty_nonnegated(void)
{
uint32_t tokens[] = { META_CLASS_EMPTY, META_CLASS_END };
uint32_t *pptr = tokens;
PCRE2_UCHAR codebuf[8] = {0};
PCRE2_UCHAR *pcode = codebuf;
eclass_op_info oi;
BOOL ok = test_compile_class_juxtaposition(NULL, FALSE, &pptr, &pcode, &oi, NULL);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_UINT32(META_CLASS_END, *pptr); /* stops at END */
TEST_ASSERT_EQUAL_UINT(1, oi.length);
TEST_ASSERT_EQUAL_UINT8(ECL_NONE, codebuf[0]);
TEST_ASSERT_EQUAL_PTR(codebuf + 1, pcode);
TEST_ASSERT_EQUAL_UINT8(ECL_NONE, oi.op_single_type);
TEST_ASSERT_TRUE(classbits_all_zeros(&oi));
}
/* Single operand: META_CLASS_EMPTY (negated): should yield ECL_ANY with all-one bits. */
void test_compile_class_juxtaposition_single_empty_negated(void)
{
uint32_t tokens[] = { META_CLASS_EMPTY, META_CLASS_END };
uint32_t *pptr = tokens;
PCRE2_UCHAR codebuf[8] = {0};
PCRE2_UCHAR *pcode = codebuf;
eclass_op_info oi;
BOOL ok = test_compile_class_juxtaposition(NULL, TRUE, &pptr, &pcode, &oi, NULL);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_UINT32(META_CLASS_END, *pptr);
TEST_ASSERT_EQUAL_UINT(1, oi.length);
TEST_ASSERT_EQUAL_UINT8(ECL_ANY, codebuf[0]);
TEST_ASSERT_EQUAL_PTR(codebuf + 1, pcode);
TEST_ASSERT_EQUAL_UINT8(ECL_ANY, oi.op_single_type);
TEST_ASSERT_TRUE(classbits_all_ones(&oi));
}
/* Juxtaposition of two operands (implicit OR when not negated):
[EMPTY_NOT EMPTY] -> ECL_ANY. */
void test_compile_class_juxtaposition_two_operands_or(void)
{
uint32_t tokens[] = { META_CLASS_EMPTY_NOT, META_CLASS_EMPTY, META_CLASS_END };
uint32_t *pptr = tokens;
PCRE2_UCHAR codebuf[8] = {0};
PCRE2_UCHAR *pcode = codebuf;
eclass_op_info oi;
BOOL ok = test_compile_class_juxtaposition(NULL, FALSE, &pptr, &pcode, &oi, NULL);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_UINT32(META_CLASS_END, *pptr);
TEST_ASSERT_EQUAL_UINT(1, oi.length);
TEST_ASSERT_EQUAL_UINT8(ECL_ANY, codebuf[0]);
TEST_ASSERT_EQUAL_PTR(codebuf + 1, pcode);
TEST_ASSERT_EQUAL_UINT8(ECL_ANY, oi.op_single_type);
TEST_ASSERT_TRUE(classbits_all_ones(&oi));
}
/* Juxtaposition with negated==TRUE (implicit AND of negations):
negated [EMPTY EMPTY_NOT] -> !(EMPTY) && !(EMPTY_NOT) -> ANY && NONE -> NONE. */
void test_compile_class_juxtaposition_two_operands_negated_and(void)
{
uint32_t tokens[] = { META_CLASS_EMPTY, META_CLASS_EMPTY_NOT, META_CLASS_END };
uint32_t *pptr = tokens;
PCRE2_UCHAR codebuf[8] = {0};
PCRE2_UCHAR *pcode = codebuf;
eclass_op_info oi;
BOOL ok = test_compile_class_juxtaposition(NULL, TRUE, &pptr, &pcode, &oi, NULL);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_UINT32(META_CLASS_END, *pptr);
TEST_ASSERT_EQUAL_UINT(1, oi.length);
TEST_ASSERT_EQUAL_UINT8(ECL_NONE, codebuf[0]);
TEST_ASSERT_EQUAL_PTR(codebuf + 1, pcode);
TEST_ASSERT_EQUAL_UINT8(ECL_NONE, oi.op_single_type);
TEST_ASSERT_TRUE(classbits_all_zeros(&oi));
}
/* Ensure compile stops before a tight binary operator (AND). */
void test_compile_class_juxtaposition_stops_before_and_operator(void)
{
uint32_t tokens[] = { META_CLASS_EMPTY, META_ECLASS_AND, META_CLASS_EMPTY_NOT, META_CLASS_END };
uint32_t *pptr = tokens;
PCRE2_UCHAR codebuf[8] = {0};
PCRE2_UCHAR *pcode = codebuf;
eclass_op_info oi;
BOOL ok = test_compile_class_juxtaposition(NULL, FALSE, &pptr, &pcode, &oi, NULL);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_UINT32(META_ECLASS_AND, *pptr); /* stops at operator */
TEST_ASSERT_EQUAL_UINT(1, oi.length);
TEST_ASSERT_EQUAL_UINT8(ECL_NONE, codebuf[0]);
TEST_ASSERT_EQUAL_PTR(codebuf + 1, pcode);
TEST_ASSERT_TRUE(classbits_all_zeros(&oi));
}
/* Length-only mode: juxtaposition of three operands should accumulate length of 3
(no operators emitted). */
void test_compile_class_juxtaposition_length_only_accumulates_operands(void)
{
uint32_t tokens[] = { META_CLASS_EMPTY_NOT, META_CLASS_EMPTY, META_CLASS_EMPTY, META_CLASS_END };
uint32_t *pptr = tokens;
PCRE2_UCHAR codebuf[8] = {0};
PCRE2_UCHAR *pcode = codebuf; /* should remain unchanged */
eclass_op_info oi;
PCRE2_SIZE length = 0;
BOOL ok = test_compile_class_juxtaposition(NULL, FALSE, &pptr, &pcode, &oi, &length);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_UINT32(META_CLASS_END, *pptr);
TEST_ASSERT_EQUAL_UINT(3, length);
TEST_ASSERT_EQUAL_PTR(codebuf, pcode); /* in length-only mode, code pointer not advanced */
}
/* Juxtaposition with negated==TRUE across three operands reduces via AND of negations.
Input: [EMPTY_NOT, EMPTY_NOT, EMPTY] -> (!ANY && !ANY && !NONE) -> (NONE && NONE && ANY) -> NONE. */
void test_compile_class_juxtaposition_three_operands_negated(void)
{
uint32_t tokens[] = { META_CLASS_EMPTY_NOT, META_CLASS_EMPTY_NOT, META_CLASS_EMPTY, META_CLASS_END };
uint32_t *pptr = tokens;
PCRE2_UCHAR codebuf[8] = {0};
PCRE2_UCHAR *pcode = codebuf;
eclass_op_info oi;
BOOL ok = test_compile_class_juxtaposition(NULL, TRUE, &pptr, &pcode, &oi, NULL);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_UINT32(META_CLASS_END, *pptr);
TEST_ASSERT_EQUAL_UINT(1, oi.length);
TEST_ASSERT_EQUAL_UINT8(ECL_NONE, codebuf[0]);
TEST_ASSERT_TRUE(classbits_all_zeros(&oi));
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_compile_class_juxtaposition_single_empty_nonnegated);
RUN_TEST(test_compile_class_juxtaposition_single_empty_negated);
RUN_TEST(test_compile_class_juxtaposition_two_operands_or);
RUN_TEST(test_compile_class_juxtaposition_two_operands_negated_and);
RUN_TEST(test_compile_class_juxtaposition_stops_before_and_operator);
RUN_TEST(test_compile_class_juxtaposition_length_only_accumulates_operands);
RUN_TEST(test_compile_class_juxtaposition_three_operands_negated);
return UNITY_END();
}