You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
6.7 KiB
C++
186 lines
6.7 KiB
C++
#include "pattern_parse.hpp"
|
|
|
|
#include <libshit/doctest.hpp>
|
|
|
|
namespace Neptools::Test
|
|
{
|
|
TEST_SUITE_BEGIN("Neptools::Pattern");
|
|
|
|
// static test...
|
|
auto fuck_you_cpp_committee = NEPTOOLS_PATTERN("01 02 03 04");
|
|
static_assert(std::is_same_v<
|
|
decltype(fuck_you_cpp_committee),
|
|
PatternParse::Pattern<
|
|
PatternParse::ByteSequence<1,2,3,4>,
|
|
PatternParse::ByteSequence<0xff,0xff,0xff,0xff>>>,
|
|
"simple pattern");
|
|
|
|
auto why_cant_I_use_fucking_lambdas = NEPTOOLS_PATTERN("11 05 f3 14");
|
|
static_assert(std::is_same_v<
|
|
decltype(why_cant_I_use_fucking_lambdas),
|
|
PatternParse::Pattern<
|
|
PatternParse::ByteSequence<0x11,0x05,0xf3,0x14>,
|
|
PatternParse::ByteSequence<0xff,0xff,0xff,0xff>>>,
|
|
"multi digit");
|
|
|
|
auto in_an_unevaluated_context_like_decltype = NEPTOOLS_PATTERN("11 5 f3 4");
|
|
static_assert(std::is_same_v<
|
|
decltype(in_an_unevaluated_context_like_decltype),
|
|
PatternParse::Pattern<
|
|
PatternParse::ByteSequence<0x11,0x05,0xf3,0x04>,
|
|
PatternParse::ByteSequence<0xff,0xff,0xff,0xff>>>,
|
|
"shortcuts");
|
|
|
|
auto or_why_cant_you_add_a_sane_way_to_use = NEPTOOLS_PATTERN("11 ?? f3 04");
|
|
static_assert(std::is_same_v<
|
|
decltype(or_why_cant_you_add_a_sane_way_to_use),
|
|
PatternParse::Pattern<
|
|
PatternParse::ByteSequence<0x11,0x00,0xf3,0x04>,
|
|
PatternParse::ByteSequence<0xff,0x00,0xff,0xff>>>,
|
|
"placeholder");
|
|
|
|
auto fucking_strings_as_template_arguments = NEPTOOLS_PATTERN("11 ? f3 04");
|
|
static_assert(std::is_same_v<
|
|
decltype(fucking_strings_as_template_arguments),
|
|
PatternParse::Pattern<
|
|
PatternParse::ByteSequence<0x11,0x00,0xf3,0x04>,
|
|
PatternParse::ByteSequence<0xff,0x00,0xff,0xff>>>,
|
|
"short placeholder");
|
|
// PS. you should add ctr instead of shit like a wrapper around cairo
|
|
|
|
auto with_mask = NEPTOOLS_PATTERN("11 22/ff 33/f0 44/77 55/00");
|
|
static_assert(std::is_same_v<
|
|
decltype(with_mask),
|
|
PatternParse::Pattern<
|
|
PatternParse::ByteSequence<0x11, 0x22, 0x30, 0x44, 0x00>,
|
|
PatternParse::ByteSequence<0xff, 0xff, 0xf0, 0x77, 0x00>>>);
|
|
|
|
Byte data[] = {
|
|
/* 00 */ 0xff, 0xf0, 0x64, 0x22, 0x50, 0xca, 0x9f, 0x23,
|
|
/* 08 */ 0x92, 0xf7, 0xb3, 0x8f, 0xb1, 0x30, 0x8a, 0xd6,
|
|
/* 10 */ 0x1e, 0x38, 0xd8, 0xf3, 0xa7, 0xfa, 0x98, 0xee,
|
|
/* 18 */ 0x58, 0xec, 0x21, 0xa8, 0xfe, 0x00, 0x1c, 0xfb,
|
|
/* 20 */ 0x5e, 0x0a, 0x48, 0x38, 0xc5, 0x64, 0xb5, 0xbe,
|
|
/* 28 */ 0xc1, 0x48, 0xdd, 0x7f, 0x3e, 0x58, 0xec, 0x21,
|
|
/* 30 */ 0x82, 0xf4, 0xca, 0x11, 0x47, 0x22, 0xcf, 0x98,
|
|
/* 38 */ 0x40, 0xfe, 0x18, 0x0e, 0x2e, 0xb9, 0xfc, 0xce,
|
|
};
|
|
TEST_CASE("simple patterns")
|
|
{
|
|
Pattern p = NEPTOOLS_PATTERN("a8 fe 0 1c"); //middle
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == data + 0x1b);
|
|
CHECK(p.Find({data, sizeof(data)}) == data + 0x1b);
|
|
|
|
p = NEPTOOLS_PATTERN("ff f0 64"); //beginning
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == data);
|
|
CHECK(p.Find({data, sizeof(data)}) == data);
|
|
|
|
p = NEPTOOLS_PATTERN("18 e 2e b9 fc ce"); //end
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == data + 0x3a);
|
|
CHECK(p.Find({data, sizeof(data)}) == data + 0x3a);
|
|
}
|
|
TEST_CASE("simple not match")
|
|
{
|
|
auto p = NEPTOOLS_PATTERN("12 34 56 76");
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
|
|
CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
|
|
}
|
|
TEST_CASE("multiple match")
|
|
{
|
|
auto p = NEPTOOLS_PATTERN("58 ec 21");
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
|
|
CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
|
|
}
|
|
|
|
TEST_CASE("wildcards")
|
|
{
|
|
Pattern p = NEPTOOLS_PATTERN("48 ? c5 ? ? be"); // mid
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == data + 0x22);
|
|
CHECK(p.Find({data, sizeof(data)}) == data + 0x22);
|
|
|
|
p = NEPTOOLS_PATTERN("ff ? ? 22 50"); // begin
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == data);
|
|
CHECK(p.Find({data, sizeof(data)}) == data);
|
|
|
|
|
|
p = NEPTOOLS_PATTERN("e ? b9 ? ce"); // end
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == data + 0x3b);
|
|
CHECK(p.Find({data, sizeof(data)}) == data + 0x3b);
|
|
|
|
p = NEPTOOLS_PATTERN("? ? fe 00 ?"); // mid
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == data + 0x1a);
|
|
CHECK(p.Find({data, sizeof(data)}) == data + 0x1a);
|
|
|
|
p = NEPTOOLS_PATTERN("? ? 64 22 ?"); // begin
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == data);
|
|
CHECK(p.Find({data, sizeof(data)}) == data);
|
|
|
|
p = NEPTOOLS_PATTERN("? 2e b9 ? ?"); // end
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == data + 0x3b);
|
|
CHECK(p.Find({data, sizeof(data)}) == data + 0x3b);
|
|
}
|
|
TEST_CASE("wildcards not match")
|
|
{
|
|
Pattern p = NEPTOOLS_PATTERN("12 34 ?? 56 ?? 78");
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
|
|
CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
|
|
|
|
p = NEPTOOLS_PATTERN("? ? 12 34 56");
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
|
|
CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
|
|
|
|
p = NEPTOOLS_PATTERN("12 34 ? 56 ? ? ?");
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
|
|
CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
|
|
}
|
|
TEST_CASE("wildcards multiple match")
|
|
{
|
|
Pattern p = NEPTOOLS_PATTERN("58 ? 21");
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
|
|
CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
|
|
|
|
p = NEPTOOLS_PATTERN("? 58 ? ?");
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
|
|
CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
|
|
|
|
p = NEPTOOLS_PATTERN("? ? ? ?");
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
|
|
CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
|
|
}
|
|
|
|
TEST_CASE("mask")
|
|
{
|
|
Byte pat[] = { 0x58, 0xe0, 0x21, 0x28, 0x3e };
|
|
Byte mask[] = { 0xff, 0xf0, 0xff, 0x2f, 0x3f };
|
|
auto p = Pattern{pat, mask, 5};
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == data + 0x18);
|
|
CHECK(p.Find({data, sizeof(data)}) == data + 0x18);
|
|
}
|
|
|
|
TEST_CASE("mask no match")
|
|
{
|
|
Byte pat[] = { 0x58, 0xe0, 0x21, 0x18, 0x3e };
|
|
Byte mask[] = { 0xff, 0xf0, 0xff, 0x1f, 0x3f };
|
|
auto p = Pattern{pat, mask, 5};
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
|
|
CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
|
|
}
|
|
|
|
TEST_CASE("mask no 0xff")
|
|
{
|
|
Byte pat[] = { 0x58, 0xe0, 0x20, 0x28, 0x3e };
|
|
Byte mask[] = { 0x5f, 0xf0, 0xf2, 0x2f, 0x3f };
|
|
auto p = Pattern{pat, mask, 5};
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == data + 0x18);
|
|
CHECK(p.Find({data, sizeof(data)}) == data + 0x18);
|
|
|
|
Byte pat2[] = { 0x58, 0xe0, 0x20, 0x18, 0x3e };
|
|
Byte mask2[] = { 0x5f, 0xf0, 0xf2, 0x1f, 0x3f };
|
|
p = Pattern{pat2, mask2, 5};
|
|
CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
|
|
CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
|
|
}
|
|
|
|
TEST_SUITE_END();
|
|
}
|