|
|
#include "unity/unity.h" |
|
|
#define PCRE2_CODE_UNIT_WIDTH 8 |
|
|
#include "pcre2.h" |
|
|
#include "pcre2_compile.h" |
|
|
|
|
|
#include <string.h> |
|
|
#include <stdint.h> |
|
|
#include <stdlib.h> |
|
|
#include <stdbool.h> |
|
|
|
|
|
|
|
|
|
|
|
extern BOOL test_compile_eclass_nested(void *context, |
|
|
BOOL negated, |
|
|
uint32_t **pptr, |
|
|
PCRE2_UCHAR **pcode, |
|
|
eclass_op_info *pop_info, |
|
|
PCRE2_SIZE *lengthptr); |
|
|
|
|
|
static void assert_bits_all(uint8_t *bits, uint8_t value) |
|
|
{ |
|
|
for (int i = 0; i < 32; i++) |
|
|
{ |
|
|
TEST_ASSERT_EQUAL_HEX8_MESSAGE(value, bits[i], "Bitset value mismatch"); |
|
|
} |
|
|
} |
|
|
|
|
|
static void assert_single_op(const eclass_op_info *info, int expected_op) |
|
|
{ |
|
|
TEST_ASSERT_EQUAL_UINT_MESSAGE(1, info->length, "Expected single opcode length"); |
|
|
TEST_ASSERT_EQUAL_INT_MESSAGE(expected_op, info->op_single_type, "op_single_type mismatch"); |
|
|
TEST_ASSERT_NOT_NULL(info->code_start); |
|
|
TEST_ASSERT_EQUAL_INT8_MESSAGE((int8_t)expected_op, (int8_t)info->code_start[0], "Emitted opcode mismatch"); |
|
|
} |
|
|
|
|
|
void setUp(void) { |
|
|
|
|
|
} |
|
|
|
|
|
void tearDown(void) { |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void test_compile_eclass_nested_empty_returns_none(void) |
|
|
{ |
|
|
uint32_t tokens[] = { |
|
|
(META_CLASS | CLASS_IS_ECLASS), |
|
|
META_CLASS_EMPTY, |
|
|
META_CLASS_END |
|
|
}; |
|
|
uint32_t *ptr = tokens; |
|
|
PCRE2_UCHAR codebuf[16] = {0}; |
|
|
PCRE2_UCHAR *code = codebuf; |
|
|
eclass_op_info info; |
|
|
|
|
|
BOOL ok = test_compile_eclass_nested(NULL, FALSE, &ptr, &code, &info, NULL); |
|
|
TEST_ASSERT_TRUE(ok); |
|
|
TEST_ASSERT_EQUAL_UINT32(META_CLASS_END, *ptr); |
|
|
assert_single_op(&info, ECL_NONE); |
|
|
assert_bits_all(info.bits.classbits, 0x00); |
|
|
TEST_ASSERT_EQUAL_PTR(info.code_start + info.length, code); |
|
|
} |
|
|
|
|
|
|
|
|
void test_compile_eclass_nested_empty_with_outer_not_returns_any(void) |
|
|
{ |
|
|
uint32_t tokens[] = { |
|
|
(META_CLASS_NOT | CLASS_IS_ECLASS), |
|
|
META_CLASS_EMPTY, |
|
|
META_CLASS_END |
|
|
}; |
|
|
uint32_t *ptr = tokens; |
|
|
PCRE2_UCHAR codebuf[16] = {0}; |
|
|
PCRE2_UCHAR *code = codebuf; |
|
|
eclass_op_info info; |
|
|
|
|
|
BOOL ok = test_compile_eclass_nested(NULL, FALSE, &ptr, &code, &info, NULL); |
|
|
TEST_ASSERT_TRUE(ok); |
|
|
TEST_ASSERT_EQUAL_UINT32(META_CLASS_END, *ptr); |
|
|
assert_single_op(&info, ECL_ANY); |
|
|
assert_bits_all(info.bits.classbits, 0xFF); |
|
|
TEST_ASSERT_EQUAL_PTR(info.code_start + info.length, code); |
|
|
} |
|
|
|
|
|
|
|
|
void test_compile_eclass_nested_unary_not_operator(void) |
|
|
{ |
|
|
uint32_t tokens[] = { |
|
|
(META_CLASS | CLASS_IS_ECLASS), |
|
|
META_ECLASS_NOT, |
|
|
META_CLASS_EMPTY, |
|
|
META_CLASS_END |
|
|
}; |
|
|
uint32_t *ptr = tokens; |
|
|
PCRE2_UCHAR codebuf[16] = {0}; |
|
|
PCRE2_UCHAR *code = codebuf; |
|
|
eclass_op_info info; |
|
|
|
|
|
BOOL ok = test_compile_eclass_nested(NULL, FALSE, &ptr, &code, &info, NULL); |
|
|
TEST_ASSERT_TRUE(ok); |
|
|
TEST_ASSERT_EQUAL_UINT32(META_CLASS_END, *ptr); |
|
|
assert_single_op(&info, ECL_ANY); |
|
|
assert_bits_all(info.bits.classbits, 0xFF); |
|
|
TEST_ASSERT_EQUAL_PTR(info.code_start + info.length, code); |
|
|
} |
|
|
|
|
|
|
|
|
void test_compile_eclass_nested_binary_and_folding(void) |
|
|
{ |
|
|
uint32_t tokens[] = { |
|
|
(META_CLASS | CLASS_IS_ECLASS), |
|
|
META_CLASS_EMPTY, |
|
|
META_ECLASS_AND, |
|
|
META_CLASS_EMPTY_NOT, |
|
|
META_CLASS_END |
|
|
}; |
|
|
uint32_t *ptr = tokens; |
|
|
PCRE2_UCHAR codebuf[32] = {0}; |
|
|
PCRE2_UCHAR *code = codebuf; |
|
|
eclass_op_info info; |
|
|
|
|
|
BOOL ok = test_compile_eclass_nested(NULL, FALSE, &ptr, &code, &info, NULL); |
|
|
TEST_ASSERT_TRUE(ok); |
|
|
TEST_ASSERT_EQUAL_UINT32(META_CLASS_END, *ptr); |
|
|
assert_single_op(&info, ECL_NONE); |
|
|
assert_bits_all(info.bits.classbits, 0x00); |
|
|
TEST_ASSERT_EQUAL_PTR(info.code_start + info.length, code); |
|
|
} |
|
|
|
|
|
|
|
|
void test_compile_eclass_nested_binary_or_folding(void) |
|
|
{ |
|
|
uint32_t tokens[] = { |
|
|
(META_CLASS | CLASS_IS_ECLASS), |
|
|
META_CLASS_EMPTY, |
|
|
META_ECLASS_OR, |
|
|
META_CLASS_EMPTY_NOT, |
|
|
META_CLASS_END |
|
|
}; |
|
|
uint32_t *ptr = tokens; |
|
|
PCRE2_UCHAR codebuf[32] = {0}; |
|
|
PCRE2_UCHAR *code = codebuf; |
|
|
eclass_op_info info; |
|
|
|
|
|
BOOL ok = test_compile_eclass_nested(NULL, FALSE, &ptr, &code, &info, NULL); |
|
|
TEST_ASSERT_TRUE(ok); |
|
|
TEST_ASSERT_EQUAL_UINT32(META_CLASS_END, *ptr); |
|
|
assert_single_op(&info, ECL_ANY); |
|
|
assert_bits_all(info.bits.classbits, 0xFF); |
|
|
TEST_ASSERT_EQUAL_PTR(info.code_start + info.length, code); |
|
|
} |
|
|
|
|
|
|
|
|
void test_compile_eclass_nested_binary_sub_folding(void) |
|
|
{ |
|
|
uint32_t tokens[] = { |
|
|
(META_CLASS | CLASS_IS_ECLASS), |
|
|
META_CLASS_EMPTY_NOT, |
|
|
META_ECLASS_SUB, |
|
|
META_CLASS_EMPTY_NOT, |
|
|
META_CLASS_END |
|
|
}; |
|
|
uint32_t *ptr = tokens; |
|
|
PCRE2_UCHAR codebuf[32] = {0}; |
|
|
PCRE2_UCHAR *code = codebuf; |
|
|
eclass_op_info info; |
|
|
|
|
|
BOOL ok = test_compile_eclass_nested(NULL, FALSE, &ptr, &code, &info, NULL); |
|
|
TEST_ASSERT_TRUE(ok); |
|
|
TEST_ASSERT_EQUAL_UINT32(META_CLASS_END, *ptr); |
|
|
assert_single_op(&info, ECL_NONE); |
|
|
assert_bits_all(info.bits.classbits, 0x00); |
|
|
TEST_ASSERT_EQUAL_PTR(info.code_start + info.length, code); |
|
|
} |
|
|
|
|
|
|
|
|
void test_compile_eclass_nested_binary_xor_folding(void) |
|
|
{ |
|
|
uint32_t tokens[] = { |
|
|
(META_CLASS | CLASS_IS_ECLASS), |
|
|
META_CLASS_EMPTY_NOT, |
|
|
META_ECLASS_XOR, |
|
|
META_CLASS_EMPTY_NOT, |
|
|
META_CLASS_END |
|
|
}; |
|
|
uint32_t *ptr = tokens; |
|
|
PCRE2_UCHAR codebuf[32] = {0}; |
|
|
PCRE2_UCHAR *code = codebuf; |
|
|
eclass_op_info info; |
|
|
|
|
|
BOOL ok = test_compile_eclass_nested(NULL, FALSE, &ptr, &code, &info, NULL); |
|
|
TEST_ASSERT_TRUE(ok); |
|
|
TEST_ASSERT_EQUAL_UINT32(META_CLASS_END, *ptr); |
|
|
assert_single_op(&info, ECL_NONE); |
|
|
assert_bits_all(info.bits.classbits, 0x00); |
|
|
TEST_ASSERT_EQUAL_PTR(info.code_start + info.length, code); |
|
|
} |
|
|
|
|
|
|
|
|
void test_compile_eclass_nested_with_nested_operand(void) |
|
|
{ |
|
|
uint32_t tokens[] = { |
|
|
(META_CLASS | CLASS_IS_ECLASS), |
|
|
|
|
|
(META_CLASS | CLASS_IS_ECLASS), |
|
|
META_CLASS_EMPTY_NOT, |
|
|
META_CLASS_END, |
|
|
META_ECLASS_AND, |
|
|
META_CLASS_EMPTY, |
|
|
META_CLASS_END |
|
|
}; |
|
|
uint32_t *ptr = tokens; |
|
|
PCRE2_UCHAR codebuf[32] = {0}; |
|
|
PCRE2_UCHAR *code = codebuf; |
|
|
eclass_op_info info; |
|
|
|
|
|
BOOL ok = test_compile_eclass_nested(NULL, FALSE, &ptr, &code, &info, NULL); |
|
|
TEST_ASSERT_TRUE(ok); |
|
|
TEST_ASSERT_EQUAL_UINT32(META_CLASS_END, *ptr); |
|
|
assert_single_op(&info, ECL_NONE); |
|
|
assert_bits_all(info.bits.classbits, 0x00); |
|
|
TEST_ASSERT_EQUAL_PTR(info.code_start + info.length, code); |
|
|
} |
|
|
|
|
|
|
|
|
void test_compile_eclass_nested_lengthptr_single_operand_counts_one(void) |
|
|
{ |
|
|
uint32_t tokens[] = { |
|
|
(META_CLASS | CLASS_IS_ECLASS), |
|
|
META_CLASS_EMPTY_NOT, |
|
|
META_CLASS_END |
|
|
}; |
|
|
uint32_t *ptr = tokens; |
|
|
PCRE2_UCHAR codebuf[16] = {0}; |
|
|
PCRE2_UCHAR *code = codebuf; |
|
|
eclass_op_info info; |
|
|
PCRE2_SIZE length = 0; |
|
|
|
|
|
BOOL ok = test_compile_eclass_nested(NULL, FALSE, &ptr, &code, &info, &length); |
|
|
TEST_ASSERT_TRUE(ok); |
|
|
TEST_ASSERT_EQUAL_UINT32(META_CLASS_END, *ptr); |
|
|
TEST_ASSERT_EQUAL_UINT(1, length); |
|
|
|
|
|
TEST_ASSERT_EQUAL_PTR(codebuf, code); |
|
|
} |
|
|
|
|
|
int main(void) |
|
|
{ |
|
|
UNITY_BEGIN(); |
|
|
RUN_TEST(test_compile_eclass_nested_empty_returns_none); |
|
|
RUN_TEST(test_compile_eclass_nested_empty_with_outer_not_returns_any); |
|
|
RUN_TEST(test_compile_eclass_nested_unary_not_operator); |
|
|
RUN_TEST(test_compile_eclass_nested_binary_and_folding); |
|
|
RUN_TEST(test_compile_eclass_nested_binary_or_folding); |
|
|
RUN_TEST(test_compile_eclass_nested_binary_sub_folding); |
|
|
RUN_TEST(test_compile_eclass_nested_binary_xor_folding); |
|
|
RUN_TEST(test_compile_eclass_nested_with_nested_operand); |
|
|
RUN_TEST(test_compile_eclass_nested_lengthptr_single_operand_counts_one); |
|
|
return UNITY_END(); |
|
|
} |