4141using modsecurity_test::UnitTest;
4242using modsecurity_test::ModSecurityTest;
4343using modsecurity_test::ModSecurityTestResults;
44+ using modsecurity::ModSecurity;
45+ using modsecurity::Rule;
46+ using modsecurity::Rules;
47+ using modsecurity::Transaction;
4448using modsecurity::actions::transformations::Transformation;
4549using modsecurity::operators::Operator;
4650
@@ -53,8 +57,20 @@ void print_help() {
5357 std::cout << std::endl;
5458}
5559
60+ static std::vector<std::string> get_capturing_groups (Transaction &transaction) {
61+ // capturing groups are stored in the TX collection as "0", "1", and so on
62+ std::vector<std::string> res;
63+ for (int i = 0 ;; i++) {
64+ const std::string key = std::to_string (i);
65+ auto s = transaction.m_collections .m_tx_collection ->resolveFirst (key);
66+ if (s == NULL ) break ;
67+ res.push_back (*s);
68+ }
69+ return res;
70+ }
5671
57- void perform_unit_test (ModSecurityTest<UnitTest> *test, UnitTest *t,
72+ static void perform_unit_test (ModSecurity *modsec,
73+ ModSecurityTest<UnitTest> *test, UnitTest *t,
5874 ModSecurityTestResults<UnitTest>* res) {
5975 std::string error;
6076 bool found = true ;
@@ -77,11 +93,27 @@ void perform_unit_test(ModSecurityTest<UnitTest> *test, UnitTest *t,
7793 }
7894
7995 if (t->type == " op" ) {
96+ Rules rules{};
97+ Transaction transaction{modsec, &rules, NULL };
8098 Operator *op = Operator::instantiate (t->name , t->param );
99+ Rule rule{NULL , NULL , NULL , " " , 1 };
100+
101+ // Rx operator won't capture groups otherwise
102+ rule.m_containsCaptureAction = true ;
103+
81104 op->init (t->filename , &error);
82- int ret = op->evaluate (NULL , NULL , t->input , NULL );
105+ int ret = op->evaluate (&transaction, &rule , t->input , NULL );
83106 t->obtained = ret;
84- if (ret != t->ret ) {
107+
108+ bool pass = (ret == t->ret );
109+ if (t->re_groups .size () > 0 ) {
110+ t->obtained_re_groups = get_capturing_groups (transaction);
111+ if (t->re_groups != t->obtained_re_groups ) {
112+ pass = false ;
113+ }
114+ }
115+
116+ if (!pass) {
85117 res->push_back (t);
86118 if (test->m_automake_output ) {
87119 std::cout << " FAIL " ;
@@ -152,6 +184,8 @@ int main(int argc, char **argv) {
152184 test.load_tests (" test-cases/secrules-language-tests/transformations" );
153185 }
154186
187+ ModSecurity modsec{};
188+
155189 for (std::pair<std::string, std::vector<UnitTest *> *> a : test) {
156190 std::vector<UnitTest *> *tests = a.second ;
157191
@@ -162,7 +196,7 @@ int main(int argc, char **argv) {
162196 if (!test.m_automake_output ) {
163197 std::cout << " " << a.first << " ...\t " ;
164198 }
165- perform_unit_test (&test, t, &r);
199+ perform_unit_test (&modsec, & test, t, &r);
166200
167201 if (!test.m_automake_output ) {
168202 int skp = 0 ;
0 commit comments