1919#include < iostream>
2020#include < ctime>
2121#include < string>
22+ #include < cassert>
2223
2324#include " modsecurity/rules_set.h"
2425#include " modsecurity/modsecurity.h"
2526#include " src/operators/operator.h"
2627#include " src/actions/transformations/transformation.h"
28+ #include " src/actions/capture.h"
2729#include " modsecurity/transaction.h"
2830#include " modsecurity/actions/action.h"
2931
4042using modsecurity_test::UnitTest;
4143using modsecurity_test::ModSecurityTest;
4244using modsecurity_test::ModSecurityTestResults;
45+ using modsecurity::ModSecurity;
46+ using modsecurity::RuleWithActions;
47+ using modsecurity::Transaction;
4348using modsecurity::actions::transformations::Transformation;
4449using modsecurity::operators::Operator;
4550
@@ -52,8 +57,30 @@ void print_help() {
5257 std::cout << std::endl;
5358}
5459
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+ }
71+
72+ static std::unique_ptr<RuleWithActions> create_fake_capture_rule () {
73+ auto actions = new modsecurity::Actions;
74+ actions->push_back (new modsecurity::actions::Capture (" " ));
75+ auto rule = std::unique_ptr<RuleWithActions>(new RuleWithActions{actions, nullptr , std::unique_ptr<std::string>(new std::string (" " )), 1 });
76+
77+ assert (rule->hasCaptureAction ());
5578
56- void perform_unit_test (ModSecurityTest<UnitTest> *test, UnitTest *t,
79+ return rule;
80+ }
81+
82+ static void perform_unit_test (ModSecurity *modsec,
83+ ModSecurityTest<UnitTest> *test, UnitTest *t,
5784 ModSecurityTestResults<UnitTest>* res) {
5885 std::string error;
5986 bool found = true ;
@@ -76,11 +103,26 @@ void perform_unit_test(ModSecurityTest<UnitTest> *test, UnitTest *t,
76103 }
77104
78105 if (t->type == " op" ) {
106+ modsecurity::RulesSet rules{};
107+ Transaction transaction{modsec, &rules, NULL };
79108 Operator *op = Operator::instantiate (t->name , t->param );
109+
110+ // Rx operator won't capture groups otherwise
111+ auto rule = create_fake_capture_rule ();
112+
80113 op->init (t->filename , &error);
81- int ret = op->evaluate (NULL , NULL , t->input , NULL );
114+ int ret = op->evaluate (&transaction, rule. get () , t->input , NULL );
82115 t->obtained = ret;
83- if (ret != t->ret ) {
116+
117+ bool pass = (ret == t->ret );
118+ if (t->re_groups .size () > 0 ) {
119+ t->obtained_re_groups = get_capturing_groups (transaction);
120+ if (t->re_groups != t->obtained_re_groups ) {
121+ pass = false ;
122+ }
123+ }
124+
125+ if (!pass) {
84126 res->push_back (t);
85127 if (test->m_automake_output ) {
86128 std::cout << " FAIL " ;
@@ -151,6 +193,8 @@ int main(int argc, char **argv) {
151193 test.load_tests (" test-cases/secrules-language-tests/transformations" );
152194 }
153195
196+ ModSecurity modsec{};
197+
154198 for (std::pair<std::string, std::vector<UnitTest *> *> a : test) {
155199 std::vector<UnitTest *> *tests = a.second ;
156200
@@ -161,7 +205,7 @@ int main(int argc, char **argv) {
161205 if (!test.m_automake_output ) {
162206 std::cout << " " << a.first << " ...\t " ;
163207 }
164- perform_unit_test (&test, t, &r);
208+ perform_unit_test (&modsec, & test, t, &r);
165209
166210 if (!test.m_automake_output ) {
167211 int skp = 0 ;
0 commit comments