File size: 6,103 Bytes
864071c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
#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();
} |