pcre2 / tests /tests_pcre2_compile_class_compile_class_binary_loose.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>
/* Pull in internal tokens/types needed for building meta streams and inspecting results. */
#include "pcre2_compile.h"
/* The target has a wrapper compiled in the module. We declare it with an
old-style prototype to avoid needing the internal typedef for eclass_context. */
extern BOOL test_compile_class_binary_loose();
static int bits_all_ones(const eclass_op_info *info)
{
for (int i = 0; i < 8; i++) {
if (info->bits.classwords[i] != 0xffffffffu) return 0;
}
return 1;
}
static int bits_all_zero(const eclass_op_info *info)
{
for (int i = 0; i < 8; i++) {
if (info->bits.classwords[i] != 0u) return 0;
}
return 1;
}
void setUp(void) {
/* no-op */
}
void tearDown(void) {
/* no-op */
}
/* Helper to invoke the wrapper safely */
static BOOL call_loose(BOOL negated, uint32_t *tokens, PCRE2_UCHAR *code_buf,
eclass_op_info *out_info, PCRE2_SIZE *lengthptr,
uint32_t **pp_after)
{
uint32_t *pp = tokens;
PCRE2_UCHAR *pc = code_buf;
BOOL rc = ((BOOL (*)(void*, BOOL, uint32_t**, PCRE2_UCHAR**, eclass_op_info*, PCRE2_SIZE*))
test_compile_class_binary_loose)(NULL, negated, &pp, &pc, out_info, lengthptr);
if (pp_after) *pp_after = pp;
return rc;
}
void test_compile_class_binary_loose_single_operand_any(void)
{
uint32_t tokens[] = { META_CLASS_EMPTY, META_CLASS_END };
PCRE2_UCHAR code[16] = {0};
eclass_op_info info;
uint32_t *pp_after = NULL;
BOOL ok = call_loose(FALSE, tokens, code, &info, NULL, &pp_after);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(&tokens[1], pp_after); /* advanced to META_CLASS_END */
TEST_ASSERT_EQUAL_INT(ECL_ANY, info.op_single_type);
TEST_ASSERT_EQUAL_UINT32(1, info.length);
TEST_ASSERT_TRUE(bits_all_ones(&info));
TEST_ASSERT_EQUAL_UINT8(ECL_ANY, info.code_start[0]);
}
void test_compile_class_binary_loose_single_operand_negated(void)
{
uint32_t tokens[] = { META_CLASS_EMPTY, META_CLASS_END };
PCRE2_UCHAR code[16] = {0};
eclass_op_info info;
uint32_t *pp_after = NULL;
BOOL ok = call_loose(TRUE, tokens, code, &info, NULL, &pp_after);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(&tokens[1], pp_after);
TEST_ASSERT_EQUAL_INT(ECL_NONE, info.op_single_type);
TEST_ASSERT_EQUAL_UINT32(1, info.length);
TEST_ASSERT_TRUE(bits_all_zero(&info));
TEST_ASSERT_EQUAL_UINT8(ECL_NONE, info.code_start[0]);
}
void test_compile_class_binary_loose_unary_not_operand(void)
{
uint32_t tokens[] = { META_ECLASS_NOT, META_CLASS_EMPTY, META_CLASS_END };
PCRE2_UCHAR code[16] = {0};
eclass_op_info info;
uint32_t *pp_after = NULL;
BOOL ok = call_loose(FALSE, tokens, code, &info, NULL, &pp_after);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(&tokens[2], pp_after);
TEST_ASSERT_EQUAL_INT(ECL_NONE, info.op_single_type);
TEST_ASSERT_TRUE(bits_all_zero(&info));
TEST_ASSERT_EQUAL_UINT8(ECL_NONE, info.code_start[0]);
}
void test_compile_class_binary_loose_double_not_operand(void)
{
uint32_t tokens[] = { META_ECLASS_NOT, META_ECLASS_NOT, META_CLASS_EMPTY, META_CLASS_END };
PCRE2_UCHAR code[16] = {0};
eclass_op_info info;
uint32_t *pp_after = NULL;
BOOL ok = call_loose(FALSE, tokens, code, &info, NULL, &pp_after);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(&tokens[3], pp_after);
TEST_ASSERT_EQUAL_INT(ECL_ANY, info.op_single_type);
TEST_ASSERT_TRUE(bits_all_ones(&info));
TEST_ASSERT_EQUAL_UINT8(ECL_ANY, info.code_start[0]);
}
void test_compile_class_binary_loose_or_simplify(void)
{
uint32_t tokens[] = { META_CLASS_EMPTY, META_ECLASS_OR, META_CLASS_EMPTY, META_CLASS_END };
PCRE2_UCHAR code[16] = {0};
eclass_op_info info;
uint32_t *pp_after = NULL;
BOOL ok = call_loose(FALSE, tokens, code, &info, NULL, &pp_after);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(&tokens[3], pp_after);
TEST_ASSERT_EQUAL_INT(ECL_ANY, info.op_single_type);
TEST_ASSERT_TRUE(bits_all_ones(&info));
TEST_ASSERT_EQUAL_UINT32(1, info.length); /* simplified to single op */
TEST_ASSERT_EQUAL_UINT8(ECL_ANY, info.code_start[0]);
}
void test_compile_class_binary_loose_or_length_only_mode(void)
{
uint32_t tokens[] = { META_CLASS_EMPTY, META_ECLASS_OR, META_CLASS_EMPTY, META_CLASS_END };
PCRE2_UCHAR code[16] = {0};
eclass_op_info info;
PCRE2_SIZE len = 0;
PCRE2_UCHAR *code_before = code;
uint32_t *pp_after = NULL;
BOOL ok = call_loose(FALSE, tokens, code, &info, &len, &pp_after);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(code_before, code_before); /* code pointer we pass doesn't change */
TEST_ASSERT_EQUAL_PTR(&tokens[3], pp_after);
/* Two operands were encountered; even if simplified, the function accounts
for their individual writes in lengthptr mode. */
TEST_ASSERT_EQUAL_UINT32(2, len);
}
void test_compile_class_binary_loose_sub_mapping(void)
{
uint32_t tokens[] = { META_CLASS_EMPTY, META_ECLASS_SUB, META_CLASS_EMPTY, META_CLASS_END };
PCRE2_UCHAR code[16] = {0};
eclass_op_info info;
uint32_t *pp_after = NULL;
BOOL ok = call_loose(FALSE, tokens, code, &info, NULL, &pp_after);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(&tokens[3], pp_after);
TEST_ASSERT_EQUAL_INT(ECL_NONE, info.op_single_type);
TEST_ASSERT_TRUE(bits_all_zero(&info));
TEST_ASSERT_EQUAL_UINT32(1, info.length);
}
void test_compile_class_binary_loose_xor_basic(void)
{
uint32_t tokens[] = { META_CLASS_EMPTY, META_ECLASS_XOR, META_CLASS_EMPTY, META_CLASS_END };
PCRE2_UCHAR code[16] = {0};
eclass_op_info info;
uint32_t *pp_after = NULL;
BOOL ok = call_loose(FALSE, tokens, code, &info, NULL, &pp_after);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(&tokens[3], pp_after);
TEST_ASSERT_EQUAL_INT(ECL_NONE, info.op_single_type);
TEST_ASSERT_TRUE(bits_all_zero(&info));
TEST_ASSERT_EQUAL_UINT32(1, info.length);
}
void test_compile_class_binary_loose_negated_or_demorgan(void)
{
uint32_t tokens[] = { META_CLASS_EMPTY, META_ECLASS_OR, META_CLASS_EMPTY, META_CLASS_END };
PCRE2_UCHAR code[16] = {0};
eclass_op_info info;
uint32_t *pp_after = NULL;
BOOL ok = call_loose(TRUE, tokens, code, &info, NULL, &pp_after);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(&tokens[3], pp_after);
/* !(ANY || ANY) -> NONE */
TEST_ASSERT_EQUAL_INT(ECL_NONE, info.op_single_type);
TEST_ASSERT_TRUE(bits_all_zero(&info));
}
void test_compile_class_binary_loose_negated_xor_becomes_xnor(void)
{
uint32_t tokens[] = { META_CLASS_EMPTY_NOT, META_ECLASS_XOR, META_CLASS_EMPTY_NOT, META_CLASS_END };
PCRE2_UCHAR code[16] = {0};
eclass_op_info info;
uint32_t *pp_after = NULL;
BOOL ok = call_loose(TRUE, tokens, code, &info, NULL, &pp_after);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(&tokens[3], pp_after);
/* With outer negation, XOR gets complemented (XNOR); with both operands
effectively NONE under inner folding, XNOR -> ANY. */
TEST_ASSERT_EQUAL_INT(ECL_ANY, info.op_single_type);
TEST_ASSERT_TRUE(bits_all_ones(&info));
}
void test_compile_class_binary_loose_precedence_and_before_or(void)
{
/* Expression: !EMPTY && EMPTY || !EMPTY
Expected: (!ANY && ANY) || !ANY -> (NONE && ANY) || NONE -> NONE || NONE -> NONE */
uint32_t tokens[] = {
META_ECLASS_NOT, META_CLASS_EMPTY,
META_ECLASS_AND, META_CLASS_EMPTY,
META_ECLASS_OR, META_ECLASS_NOT, META_CLASS_EMPTY,
META_CLASS_END
};
PCRE2_UCHAR code[32] = {0};
eclass_op_info info;
uint32_t *pp_after = NULL;
BOOL ok = call_loose(FALSE, tokens, code, &info, NULL, &pp_after);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(&tokens[7], pp_after);
TEST_ASSERT_EQUAL_INT(ECL_NONE, info.op_single_type);
TEST_ASSERT_TRUE(bits_all_zero(&info));
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_compile_class_binary_loose_single_operand_any);
RUN_TEST(test_compile_class_binary_loose_single_operand_negated);
RUN_TEST(test_compile_class_binary_loose_unary_not_operand);
RUN_TEST(test_compile_class_binary_loose_double_not_operand);
RUN_TEST(test_compile_class_binary_loose_or_simplify);
RUN_TEST(test_compile_class_binary_loose_or_length_only_mode);
RUN_TEST(test_compile_class_binary_loose_sub_mapping);
RUN_TEST(test_compile_class_binary_loose_xor_basic);
RUN_TEST(test_compile_class_binary_loose_negated_or_demorgan);
RUN_TEST(test_compile_class_binary_loose_negated_xor_becomes_xnor);
RUN_TEST(test_compile_class_binary_loose_precedence_and_before_or);
return UNITY_END();
}