pcre2 / tests /tests_pcre2_compile_class_add_to_class.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 <stdint.h>
#include <string.h>
#include <stdlib.h>
/* We need the internal compile_block definition and classbits layout. */
#include "pcre2_compile.h"
/* Wrapper provided by the module under test. */
extern void test_add_to_class(uint32_t options, uint32_t xoptions, compile_block *cb,
uint32_t start, uint32_t end);
/* Global test state */
static compile_block g_cb;
static uint8_t g_fcc[256];
static int bit_is_set(const uint8_t *bits, uint32_t c)
{
return (bits[c >> 3] & (uint8_t)(1u << (c & 7))) != 0;
}
static void init_fcc_ascii_flipcase(uint8_t *fcc)
{
for (int i = 0; i < 256; i++) {
if (i >= 'a' && i <= 'z') fcc[i] = (uint8_t)(i - ('a' - 'A'));
else if (i >= 'A' && i <= 'Z') fcc[i] = (uint8_t)(i + ('a' - 'A'));
else fcc[i] = (uint8_t)i;
}
}
void setUp(void) {
memset(&g_cb, 0, sizeof(g_cb));
memset(g_cb.classbits.classbits, 0, 32);
init_fcc_ascii_flipcase(g_fcc);
g_cb.fcc = g_fcc; /* Used by add_to_class() for caseless folding in non-UTF mode */
}
void tearDown(void) {
/* nothing */
}
/* Tests */
void test_add_to_class_func_single_byte_sets_bit(void)
{
/* Add 'A' only */
test_add_to_class(0, 0, &g_cb, (uint32_t)'A', (uint32_t)'A');
TEST_ASSERT_TRUE(bit_is_set(g_cb.classbits.classbits, 'A'));
TEST_ASSERT_FALSE(bit_is_set(g_cb.classbits.classbits, 'A' - 1));
TEST_ASSERT_FALSE(bit_is_set(g_cb.classbits.classbits, 'A' + 1));
}
void test_add_to_class_func_range_sets_bits_and_middle_bytes_ff(void)
{
/* Range 10..250 */
memset(g_cb.classbits.classbits, 0, 32);
test_add_to_class(0, 0, &g_cb, 10u, 250u);
/* Edges */
TEST_ASSERT_FALSE(bit_is_set(g_cb.classbits.classbits, 9));
TEST_ASSERT_TRUE(bit_is_set(g_cb.classbits.classbits, 10));
TEST_ASSERT_TRUE(bit_is_set(g_cb.classbits.classbits, 127));
TEST_ASSERT_TRUE(bit_is_set(g_cb.classbits.classbits, 128));
TEST_ASSERT_TRUE(bit_is_set(g_cb.classbits.classbits, 250));
TEST_ASSERT_FALSE(bit_is_set(g_cb.classbits.classbits, 251));
/* Middle bytes should be 0xff for byte indices [2..30] */
for (int i = 2; i <= 30; i++) {
TEST_ASSERT_EQUAL_HEX8(0xFF, g_cb.classbits.classbits[i]);
}
}
void test_add_to_class_func_caseless_adds_folded_counterparts_lowercase_input(void)
{
memset(g_cb.classbits.classbits, 0, 32);
test_add_to_class(PCRE2_CASELESS, 0, &g_cb, (uint32_t)'a', (uint32_t)'c');
/* Lowercase present */
TEST_ASSERT_TRUE(bit_is_set(g_cb.classbits.classbits, 'a'));
TEST_ASSERT_TRUE(bit_is_set(g_cb.classbits.classbits, 'b'));
TEST_ASSERT_TRUE(bit_is_set(g_cb.classbits.classbits, 'c'));
/* Uppercase counterparts added */
TEST_ASSERT_TRUE(bit_is_set(g_cb.classbits.classbits, 'A'));
TEST_ASSERT_TRUE(bit_is_set(g_cb.classbits.classbits, 'B'));
TEST_ASSERT_TRUE(bit_is_set(g_cb.classbits.classbits, 'C'));
/* Outside range remain unset */
TEST_ASSERT_FALSE(bit_is_set(g_cb.classbits.classbits, 'd'));
TEST_ASSERT_FALSE(bit_is_set(g_cb.classbits.classbits, 'D'));
}
void test_add_to_class_func_caseless_adds_folded_counterparts_uppercase_input(void)
{
memset(g_cb.classbits.classbits, 0, 32);
test_add_to_class(PCRE2_CASELESS, 0, &g_cb, (uint32_t)'X', (uint32_t)'X');
TEST_ASSERT_TRUE(bit_is_set(g_cb.classbits.classbits, 'X'));
TEST_ASSERT_TRUE(bit_is_set(g_cb.classbits.classbits, 'x'));
}
void test_add_to_class_func_end_over_255_is_clamped(void)
{
memset(g_cb.classbits.classbits, 0, 32);
test_add_to_class(0, 0, &g_cb, 200u, 300u);
TEST_ASSERT_FALSE(bit_is_set(g_cb.classbits.classbits, 199));
TEST_ASSERT_TRUE(bit_is_set(g_cb.classbits.classbits, 200));
TEST_ASSERT_TRUE(bit_is_set(g_cb.classbits.classbits, 255));
/* 256+ cannot be represented in bitmap; ensure higher neighbors remain zero */
TEST_ASSERT_FALSE(bit_is_set(g_cb.classbits.classbits, 0));
}
void test_add_to_class_func_start_over_255_is_noop(void)
{
memset(g_cb.classbits.classbits, 0xAA, 32); /* Pre-fill with pattern to detect changes */
uint8_t before[32];
memcpy(before, g_cb.classbits.classbits, 32);
test_add_to_class(0, 0, &g_cb, 300u, 400u);
TEST_ASSERT_EQUAL_UINT8_ARRAY(before, g_cb.classbits.classbits, 32);
}
void test_add_to_class_func_full_range_sets_all_bits(void)
{
memset(g_cb.classbits.classbits, 0, 32);
test_add_to_class(0, 0, &g_cb, 0u, 255u);
for (int i = 0; i < 32; i++) {
TEST_ASSERT_EQUAL_HEX8(0xFF, g_cb.classbits.classbits[i]);
}
}
void test_add_to_class_func_small_partial_boundaries(void)
{
memset(g_cb.classbits.classbits, 0, 32);
test_add_to_class(0, 0, &g_cb, 7u, 9u);
TEST_ASSERT_FALSE(bit_is_set(g_cb.classbits.classbits, 6));
TEST_ASSERT_TRUE(bit_is_set(g_cb.classbits.classbits, 7));
TEST_ASSERT_TRUE(bit_is_set(g_cb.classbits.classbits, 8));
TEST_ASSERT_TRUE(bit_is_set(g_cb.classbits.classbits, 9));
TEST_ASSERT_FALSE(bit_is_set(g_cb.classbits.classbits, 10));
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_add_to_class_func_single_byte_sets_bit);
RUN_TEST(test_add_to_class_func_range_sets_bits_and_middle_bytes_ff);
RUN_TEST(test_add_to_class_func_caseless_adds_folded_counterparts_lowercase_input);
RUN_TEST(test_add_to_class_func_caseless_adds_folded_counterparts_uppercase_input);
RUN_TEST(test_add_to_class_func_end_over_255_is_clamped);
RUN_TEST(test_add_to_class_func_start_over_255_is_noop);
RUN_TEST(test_add_to_class_func_full_range_sets_all_bits);
RUN_TEST(test_add_to_class_func_small_partial_boundaries);
return UNITY_END();
}