summaryrefslogtreecommitdiffstats
path: root/modules/policy/lua-aho-corasick/tests/ac_test_aggr.cxx
blob: 4ea02bc8ab6fc1cc1cf1efde479ef97c40abb917 (plain)
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
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>

#include <stdio.h>
#include <string.h>
#include <vector>
#include <string>

#include "ac.h"
#include "ac_util.hpp"
#include "test_base.hpp"

using namespace std;

namespace {
class ACBigFileTester : public BigFileTester {
public:
    ACBigFileTester(const char* filepath) : BigFileTester(filepath){};

private:
    virtual buf_header_t* PM_Create(const char** strv, uint32* strlenv,
                                    uint32 vect_len) {
        return (buf_header_t*)ac_create(strv, strlenv, vect_len);
    }

    virtual void PM_Free(buf_header_t* PM) { ac_free(PM); }
    virtual bool Run_Helper(buf_header_t* PM);
};

class ACTestAggressive: public ACTestBase {
public:
    ACTestAggressive(const vector<const char*>& files, const char* banner)
        : ACTestBase(banner), _files(files) {}
    virtual bool Run();

private:
    void PrintSummary(int total, int fail)  {
        fprintf(stdout, "Test count : %d, fail: %d\n", total, fail);
        fflush(stdout);
    }
    vector<const char*> _files;
};

} // end of anonymous namespace

bool
ACBigFileTester::Run_Helper(buf_header_t* PM) {
    int fail = 0;
    // advance one chunk at a time.
    int len = _msg_len;
    int chunk_sz = _chunk_sz;

    vector<const char*> c_style_keys;
    for (int i = 0, e = _keys.size(); i != e; i++) {
        const char* key = _keys[i].first;
        int len = _keys[i].second;
        char *t = new char[len+1];
        memcpy(t, key, len);
        t[len] = '\0';
        c_style_keys.push_back(t);
    }

    for (int ofst = 0, chunk_idx = 0, chunk_num = _chunk_num;
         chunk_idx < chunk_num; ofst += chunk_sz, chunk_idx++) {
        const char* substring = _msg + ofst;
        ac_result_t r = ac_match((ac_t*)(void*)PM, substring , len - ofst);
        int m_b = r.match_begin;
        int m_e = r.match_end;

        if (m_b < 0 || m_e < 0 || m_e <= m_b || m_e >= len) {
            fprintf(stdout, "fail to find match substring[%d:%d])\n",
                    ofst, len - 1);
            fail ++;
            continue;
        }

        const char* match_str = _msg + len;
        int strstr_len = 0;
        int key_idx = -1;

        for (int i = 0, e = c_style_keys.size(); i != e; i++) {
            const char* key = c_style_keys[i];
            if (const char *m = strstr(substring, key)) {
                if (m < match_str) {
                    match_str = m;
                    strstr_len = _keys[i].second;
                    key_idx = i;
                }
            }
        }
        ASSERT(key_idx != -1);
        if ((match_str - substring != m_b)) {
            fprintf(stdout,
                   "Fail to find match substring[%d:%d]),"
                   " expected to find match at offset %d instead of %d\n",
                    ofst, len - 1,
                    (int)(match_str - _msg), ofst + m_b);
            fprintf(stdout, "%d vs %d (key idx %d)\n", strstr_len, m_e - m_b + 1, key_idx);
            PrintStr(stdout, match_str, strstr_len);
            fprintf(stdout, "\n");
            PrintStr(stdout, _msg + ofst + m_b,
                     m_e - m_b + 1);
            fprintf(stdout, "\n");
            fail ++;
        }
    }
    for (vector<const char*>::iterator i = c_style_keys.begin(),
            e = c_style_keys.end(); i != e; i++) {
        delete[] *i;
    }

    return fail == 0;
}

bool
ACTestAggressive::Run() {
    int fail = 0;
    for (vector<const char*>::iterator i = _files.begin(), e = _files.end();
         i != e; i++) {
        ACBigFileTester bft(*i);
        if (!bft.Run())
            fail ++;
    }
    return fail == 0;
}

bool
Run_AC_Aggressive_Test(const vector<const char*>& files) {
    ACTestAggressive t(files, "AC Aggressive test");
    t.PrintBanner();
    return t.Run();
}