pcre2 / tests /tests_pcre2_compile_class_compile_class_binary_tight.c
AryaWu's picture
Upload folder using huggingface_hub
864071c verified
#include "unity/unity.h"
#define PCRE2_CODE_UNIT_WIDTH 8
#include "pcre2.h"
/* We need internal ECLASS tokens/types and eclass_op_info. */
#include "pcre2_compile.h"
#include <string.h>
#include <stdint.h>
/* The wrapper is defined in the module, but is not declared in a header. */
extern BOOL test_compile_class_binary_tight();
void setUp(void) {
/* nothing */
}
void tearDown(void) {
/* nothing */
}
/* Helper: assert bitmap is all ones (0xFF..). */
static void assert_bits_all_ones(const eclass_op_info *op)
{
for (int i = 0; i < 8; i++) {
TEST_ASSERT_EQUAL_HEX32(0xFFFFFFFFu, op->bits.classwords[i]);
}
}
/* Helper: assert bitmap is all zeros. */
static void assert_bits_all_zeros(const eclass_op_info *op)
{
for (int i = 0; i < 8; i++) {
TEST_ASSERT_EQUAL_HEX32(0u, op->bits.classwords[i]);
}
}
/* Case 1: single operand (META_CLASS_EMPTY_NOT) -> ECL_ANY with all-ones bitmap. */
void test_compile_class_binary_tight_single_any(void)
{
/* Tokens: [META_CLASS_EMPTY_NOT] then end. */
uint32_t tokens[] = { META_CLASS_EMPTY_NOT, META_CLASS_END };
uint32_t *ptr = tokens;
uint32_t *pptr = ptr;
PCRE2_UCHAR codebuf[16];
PCRE2_UCHAR *code = codebuf;
eclass_op_info op_info;
memset(&op_info, 0, sizeof(op_info));
BOOL ok = test_compile_class_binary_tight(NULL, /*negated=*/FALSE,
&pptr, &code, &op_info,
/*lengthptr=*/NULL);
TEST_ASSERT_TRUE(ok);
/* One byte written: ECL_ANY. */
TEST_ASSERT_EQUAL_PTR(codebuf + 1, code);
TEST_ASSERT_EQUAL_UINT8(ECL_ANY, codebuf[0]);
TEST_ASSERT_EQUAL_UINT8(ECL_ANY, op_info.op_single_type);
TEST_ASSERT_EQUAL_UINT(1, op_info.length);
assert_bits_all_ones(&op_info);
/* pptr advanced to META_CLASS_END */
TEST_ASSERT_EQUAL_PTR(&tokens[1], pptr);
TEST_ASSERT_EQUAL_UINT(META_CLASS_END, *pptr);
}
/* Case 2: ANY && ANY -> ANY (no operator emitted; RHS dropped). */
void test_compile_class_binary_tight_and_any_any(void)
{
uint32_t tokens[] = { META_CLASS_EMPTY_NOT, META_ECLASS_AND, META_CLASS_EMPTY_NOT, META_CLASS_END };
uint32_t *pptr = tokens;
PCRE2_UCHAR codebuf[16];
PCRE2_UCHAR *code = codebuf;
eclass_op_info op_info;
memset(&op_info, 0, sizeof(op_info));
BOOL ok = test_compile_class_binary_tight(NULL, FALSE, &pptr, &code, &op_info, NULL);
TEST_ASSERT_TRUE(ok);
/* Still a single byte: ECL_ANY. */
TEST_ASSERT_EQUAL_PTR(codebuf + 1, code);
TEST_ASSERT_EQUAL_UINT8(ECL_ANY, codebuf[0]);
TEST_ASSERT_EQUAL_UINT8(ECL_ANY, op_info.op_single_type);
TEST_ASSERT_EQUAL_UINT(1, op_info.length);
assert_bits_all_ones(&op_info);
/* pptr should now point to META_CLASS_END */
TEST_ASSERT_EQUAL_PTR(&tokens[3], pptr);
TEST_ASSERT_EQUAL_UINT(META_CLASS_END, *pptr);
}
/* Case 3: NONE && ANY -> NONE. Use META_CLASS_EMPTY (NONE) and META_CLASS_EMPTY_NOT (ANY). */
void test_compile_class_binary_tight_and_none_any(void)
{
uint32_t tokens[] = { META_CLASS_EMPTY, META_ECLASS_AND, META_CLASS_EMPTY_NOT, META_CLASS_END };
uint32_t *pptr = tokens;
PCRE2_UCHAR codebuf[16];
PCRE2_UCHAR *code = codebuf;
eclass_op_info op_info;
memset(&op_info, 0, sizeof(op_info));
BOOL ok = test_compile_class_binary_tight(NULL, FALSE, &pptr, &code, &op_info, NULL);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(codebuf + 1, code);
TEST_ASSERT_EQUAL_UINT8(ECL_NONE, codebuf[0]);
TEST_ASSERT_EQUAL_UINT8(ECL_NONE, op_info.op_single_type);
TEST_ASSERT_EQUAL_UINT(1, op_info.length);
assert_bits_all_zeros(&op_info);
TEST_ASSERT_EQUAL_PTR(&tokens[3], pptr);
TEST_ASSERT_EQUAL_UINT(META_CLASS_END, *pptr);
}
/* Case 4: negated context flips AND to OR semantics.
Input: EMPTY && EMPTY, negated=true
EMPTY -> NONE when un-negated; with negated=true, each operand becomes ANY.
ANY || ANY -> ANY. */
void test_compile_class_binary_tight_negated_transforms_and_to_or(void)
{
uint32_t tokens[] = { META_CLASS_EMPTY, META_ECLASS_AND, META_CLASS_EMPTY, META_CLASS_END };
uint32_t *pptr = tokens;
PCRE2_UCHAR codebuf[16];
PCRE2_UCHAR *code = codebuf;
eclass_op_info op_info;
memset(&op_info, 0, sizeof(op_info));
BOOL ok = test_compile_class_binary_tight(NULL, /*negated=*/TRUE, &pptr, &code, &op_info, NULL);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(codebuf + 1, code);
TEST_ASSERT_EQUAL_UINT8(ECL_ANY, codebuf[0]);
TEST_ASSERT_EQUAL_UINT8(ECL_ANY, op_info.op_single_type);
TEST_ASSERT_EQUAL_UINT(1, op_info.length);
assert_bits_all_ones(&op_info);
TEST_ASSERT_EQUAL_PTR(&tokens[3], pptr);
TEST_ASSERT_EQUAL_UINT(META_CLASS_END, *pptr);
}
/* Case 5: length-only mode. Ensure *lengthptr increases by operand bytes and no code is written. */
void test_compile_class_binary_tight_length_only_mode(void)
{
uint32_t tokens[] = { META_CLASS_EMPTY_NOT, META_ECLASS_AND, META_CLASS_EMPTY_NOT, META_CLASS_END };
uint32_t *pptr = tokens;
PCRE2_UCHAR codebuf[16];
memset(codebuf, 0xA5, sizeof(codebuf));
PCRE2_UCHAR *code = codebuf; /* Should remain unchanged in length-only mode. */
eclass_op_info op_info;
memset(&op_info, 0, sizeof(op_info));
PCRE2_SIZE length = 0;
BOOL ok = test_compile_class_binary_tight(NULL, FALSE, &pptr, &code, &op_info, &length);
TEST_ASSERT_TRUE(ok);
/* Two operands each contribute 1 unit; no operator emitted after folding. */
TEST_ASSERT_EQUAL_UINT(2, length);
/* Code pointer should be unchanged when lengthptr != NULL. */
TEST_ASSERT_EQUAL_PTR(codebuf, code);
/* op_info still reflects the folded result (ANY, all ones). */
TEST_ASSERT_EQUAL_UINT8(ECL_ANY, op_info.op_single_type);
assert_bits_all_ones(&op_info);
TEST_ASSERT_EQUAL_PTR(&tokens[3], pptr);
TEST_ASSERT_EQUAL_UINT(META_CLASS_END, *pptr);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_compile_class_binary_tight_single_any);
RUN_TEST(test_compile_class_binary_tight_and_any_any);
RUN_TEST(test_compile_class_binary_tight_and_none_any);
RUN_TEST(test_compile_class_binary_tight_negated_transforms_and_to_or);
RUN_TEST(test_compile_class_binary_tight_length_only_mode);
return UNITY_END();
}