File: test_regexrules_main.cpp

package info (click to toggle)
source-highlight 3.1.7-1
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 10,332 kB
  • ctags: 5,233
  • sloc: sh: 11,270; cpp: 10,206; ansic: 9,515; makefile: 1,865; lex: 1,200; yacc: 1,021; php: 213; perl: 211; awk: 98; erlang: 94; lisp: 90; java: 75; ruby: 69; python: 61; asm: 43; ml: 38; ada: 36; haskell: 27; xml: 23; cs: 11; sql: 8; tcl: 6; sed: 4
file content (517 lines) | stat: -rw-r--r-- 19,235 bytes parent folder | download | duplicates (6)
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
// tests for RegexHighlightRules

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <iostream>
#include <boost/regex.hpp>

#include "asserttestexit.h"
#include "srchilite/regexrulefactory.h"
#include "srchilite/highlightrule.h"
#include "srchilite/highlighttoken.h"
#include "srchilite/highlightstateprinter.h"
#include "srchilite/matchingparameters.h"
#include <sstream>
#include "srchilite/tostringcollection.h"

using namespace std;
using namespace srchilite;

HighlightStatePrinter coutPrinter;

static void check_regex(HighlightRule *rule, const MatchingParameters &params,
        const string &s, bool shouldMatch, const string &match,
        const string &prefix, const string &suffix,
        const MatchedSubExps &subexps = MatchedSubExps());

static void check_compound_regex(HighlightRule *rule,
        const MatchingParameters &params, const string &s,
        const MatchedElements &expectedElemList, const string &prefix,
        const string &suffix);

static void check_state(const HighlightState *state,
        const MatchingParameters &params, const string &s, bool shouldMatch,
        const string &match, const string &prefix, const string &suffix,
        const string &expectedMatchingRule = "", const string &expectedElem =
                "");

void check_regex(HighlightRule *rule, const MatchingParameters &params,
        const string &s, bool shouldMatch, const string &match,
        const string &prefix, const string &suffix,
        const MatchedSubExps &subexps) {
    HighlightToken res;

    bool matched = rule->tryToMatch(s, res, params);

    assertEquals(shouldMatch, matched);

    if (matched) {
        cout << "prefix : " << res.prefix << endl;
        cout << "suffix : " << res.suffix << endl;
        cout << "matched: " << res.matched.begin()->second << endl;

        if (res.matchedSubExps.size()) {
            cout << "subexps: " << collectionToString(&(res.matchedSubExps),
                    ',') << endl;
        }

        assertEquals(match, res.matched.begin()->second);
        assertEquals(prefix, res.prefix);
        assertEquals(suffix, res.suffix);
        assertEqualsCollections(subexps, res.matchedSubExps);
    } else {
        cout << "not matched: " << s << endl;
    }
}

void check_compound_regex(HighlightRule *rule,
        const MatchingParameters &params, const string &s,
        const MatchedElements &expectedElemList, const string &prefix,
        const string &suffix) {
    HighlightToken res;

    rule->tryToMatch(s, res, params);

    assertEquals(expectedElemList.size(), res.matched.size());

    coutPrinter.printHighlightToken(&res);

    MatchedElements::const_iterator it, it2;
    for (it2 = res.matched.begin(), it = expectedElemList.begin(); it
            != expectedElemList.end(); ++it, ++it2) {
        assertEquals(it->first, it2->first);
        assertEquals(it->second, it2->second);
    }
    assertEquals(prefix, res.prefix);
    assertEquals(suffix, res.suffix);
}

void check_state(const HighlightState *state, const MatchingParameters &params,
        const string &s, bool shouldMatch, const string &match,
        const string &prefix, const string &suffix,
        const string &expectedMatchingRule, const string &expectedElem) {
    HighlightToken res;

    bool matched = state->findBestMatch(s, res, params);

    assertEquals(shouldMatch, matched);

    if (matched) {
        coutPrinter.printHighlightToken(&res);

        assertEquals(match, res.matched.begin()->second);
        assertEquals(prefix, res.prefix);
        assertEquals(suffix, res.suffix);

        if (expectedMatchingRule.size())
            assertEquals(expectedMatchingRule, res.rule->toString());

        if (expectedElem.size())
            assertEquals(expectedElem, res.matched.begin()->first);
    } else {
        cout << "not matched: " << s << endl;
    }
}

int main() {
    ostringstream printedState;
    HighlightStatePrinter printer(printedState);
    MatchingParameters params;

    cout << "*** test_regexrules" << endl;

    // first of all check the only spaces regular expression
    boost::regex onlySpaces("[[:blank:]]*");

    assertTrue(boost::regex_match(" \t \t ", onlySpaces));
    assertTrue(boost::regex_match("", onlySpaces));
    assertFalse(boost::regex_match(" a\t \t ", onlySpaces));
    assertFalse(boost::regex_match(" a ", onlySpaces));
    assertFalse(boost::regex_match("foo", onlySpaces));

    RegexRuleFactory factory;

    HighlightRulePtr rule = HighlightRulePtr(factory.createSimpleRule("foo",
            "foo|bar"));

    check_regex(rule.get(), params, "before_foo_after", true, "foo", "before_",
            "_after");
    check_regex(rule.get(), params, "before_foo", true, "foo", "before_", "");
    check_regex(rule.get(), params, "bar_after", true, "bar", "", "_after");

    check_regex(rule.get(), params, "before__after", false, "foo", "before_",
            "_after");

    WordList wordList;
    wordList.push_back("foo");
    wordList.push_back("bar");
    wordList.push_back("gogo");

    rule = HighlightRulePtr(factory.createWordListRule("foo", wordList));

    cout << "word list regex: " << rule->toString() << endl;
    assertEquals("\\<(?:foo|bar|gogo)\\>", rule->toString());

    // there's no matching since we required word boundaries
    check_regex(rule.get(), params, "before_foo_after", false, "foo",
            "before_", "_after");
    check_regex(rule.get(), params, "before_foo", false, "foo", "before_", "");
    check_regex(rule.get(), params, "bar_after", false, "bar", "", "_after");

    // now there's match
    check_regex(rule.get(), params, "before foo after", true, "foo", "before ",
            " after");
    check_regex(rule.get(), params, "before foo", true, "foo", "before ", "");
    check_regex(rule.get(), params, "bar after", true, "bar", "", " after");

    check_regex(rule.get(), params, "before__after", false, "foo", "before_",
            "_after");

    // non case sensitive version
    rule = HighlightRulePtr(factory.createWordListRule("foo", wordList, false));

    cout << "word list regex: " << rule->toString() << endl;

    assertEquals("\\<(?:[Ff][Oo][Oo]|[Bb][Aa][Rr]|[Gg][Oo][Gg][Oo])\\>",
            rule->toString());

    check_regex(rule.get(), params, "before FoO", true, "FoO", "before ", "");
    check_regex(rule.get(), params, "bAr after", true, "bAr", "", " after");

    // now the simple list version (i.e., not word list)
    rule = HighlightRulePtr(factory.createListRule("foo", wordList));

    cout << "word list regex: " << rule->toString() << endl;

    assertEquals("(?:foo|bar|gogo)", rule->toString());

    check_regex(rule.get(), params, "before_foo", true, "foo", "before_", "");
    check_regex(rule.get(), params, "bar_after", true, "bar", "", "_after");

    // search for strings delimited by A
    rule = HighlightRulePtr(factory.createLineRule("foo", "A", "A"));

    cout << "line rule: " << rule->toString() << endl;

    assertEquals("A(?:[^A])*A", rule->toString());

    check_regex(rule.get(), params, "before A foo bar A after", true,
            "A foo bar A", "before ", " after");

    // search for strings delimited by A and BC
    rule = HighlightRulePtr(factory.createLineRule("foo", "A", "B"));

    cout << "line rule: " << rule->toString() << endl;

    assertEquals("A(?:[^AB])*B", rule->toString());

    check_regex(rule.get(), params, "before A foo bar A and BC after", true,
            "A and B", "before A foo bar ", "C after");

    // search for strings delimited by < and > and escape char
    rule = HighlightRulePtr(factory.createLineRule("foo", "<", ">", "\\\\"));

    cout << "line rule: " << rule->toString() << endl;

    assertEquals("<(?:[^\\\\<\\\\>]|\\\\.)*>", rule->toString());

    check_regex(rule.get(), params, "before < foo bar \\> and > after", true,
            "< foo bar \\> and >", "before ", " after");

    // test for multiline rule without escape and non nested
    rule = HighlightRulePtr(factory.createMultiLineRule("foo", "<", ">", "",
            false));

    printer.printHighlightRule(rule.get());

    cout << "multi line rule: " << printedState.str() << endl;

    assertEquals("<", rule->toString());

    const HighlightState *nextState = rule->getNextState().get();

    assertTrue(nextState != 0);
    if (nextState) {
        HighlightRulePtr nextRule = nextState->getRuleList()[0];
        assertEquals(">", nextRule->toString());
    }

    // test for multiline rule with escape and non nested
    rule = HighlightRulePtr(factory.createMultiLineRule("foo", "<", ">",
            "\\\\", false));

    printedState.str("");
    printer.printHighlightRule(rule.get());

    cout << "multi line rule: " << printedState.str() << endl;

    assertEquals("<", rule->toString());

    nextState = rule->getNextState().get();

    assertTrue(nextState != 0);
    if (nextState) {
        HighlightRulePtr nextRule = nextState->getRuleList()[1];
        assertEquals("\\\\.", nextRule->toString());
        nextRule = nextState->getRuleList()[0];
        assertEquals(">", nextRule->toString());
        assertEquals(1, nextRule->getExitLevel());
    }

    // check state betterThan
    HighlightToken t1("", "ab", "");
    HighlightToken t2("", "bcd", "a");
    HighlightToken t3("", "bcde", "a");

    // t2 is not better than t1 since although its matching string is longer
    // also its prefix is
    assertFalse(HighlightState::betterThan(t2, t1));
    assertTrue(HighlightState::betterThan(t1, t2));

    // t2 is not better than t3 since since its matching string is smaller
    assertFalse(HighlightState::betterThan(t2, t3));
    assertTrue(HighlightState::betterThan(t3, t2));

    // now test the state matching with the above nextState
    HighlightToken token;

    // should match >
    check_state(nextState, params, "ab >", true, ">", "ab ", "");

    // should match \> since it is escaped
    check_state(nextState, params, "ab \\> bc >", true, "\\>", "ab ", " bc >");

    HighlightState classState;

    assertEquals("normal", classState.getDefaultElement());

    classState.addRule(
            HighlightRulePtr(factory.createSimpleRule("as", "as|at")));

    check_state(&classState, params, "this class foo", true, "as", "this cl",
            "s foo", "", "as");

    HighlightRulePtr keywordRule = HighlightRulePtr(factory.createSimpleRule(
            "keyword", "class"));
    classState.addRule(keywordRule);

    // now we should find a better match "class"
    check_state(&classState, params, "this class foo", true, "class", "this ",
            " foo", "class", "keyword");

    classState.addRule(HighlightRulePtr(factory.createSimpleRule("complex",
            "class[[:blank:]]+[[:word:]]+")));

    // now we should find an even better match "class foo"
    check_state(&classState, params, "this class foo", true, "class foo",
            "this ", "", "class[[:blank:]]+[[:word:]]+", "complex");

    // we don't match "class foo" but only "class" since its prefix
    // contains only spaces
    check_state(&classState, params, "\t \t class foo", true, "class",
            "\t \t ", " foo", "class", "keyword");

    classState.addRule(HighlightRulePtr(factory.createSimpleRule("foo", "bar"))); // (1)
    classState.addRule(HighlightRulePtr(factory.createSimpleRule("foo",
            "[[:word:]]+(?=[[:blank:]]*\\()"))); // (2)

    // although also the second rule matches "bar", however the first one already matched
    check_state(&classState, params, "this bar ( foo", true, "bar", "this ",
            " ( foo", "bar");
    // in this case the second rule matches only
    check_state(&classState, params, "this myfun ( foo", true, "myfun",
            "this ", " ( foo", "[[:word:]]+(?=[[:blank:]]*\\()");

    // test for nested
    HighlightState stateWithNestedRule;
    HighlightRulePtr startRule = HighlightRulePtr(factory.createMultiLineRule(
            "foo", "<", ">", "\\\\", true));

    cout << "multi line rule (nested): ";
    coutPrinter.printHighlightRule(startRule.get());
    cout << endl;

    nextState = startRule->getNextState().get();
    // the 3rd element is expected to be the same start sequence but nested and
    // with empty next state
    assertEquals("<", nextState->getRuleList()[2]->toString());
    assertTrue(nextState->getRuleList()[2]->isNested());
    assertTrue(nextState->getRuleList()[2]->getNextState().get() == 0);

    // single line automatically transformed in multi line (since nested)
    HighlightRulePtr singleNestedToMultiRule = HighlightRulePtr(
            factory.createLineRule("foo", "<", ">", "\\\\", true));

    cout << "single nested line rule (transformed): ";
    coutPrinter.printHighlightRule(singleNestedToMultiRule.get());
    cout << endl;

    nextState = singleNestedToMultiRule->getNextState().get();
    assertEquals(">", nextState->getRuleList()[0]->toString());
    assertEquals(1, nextState->getRuleList()[0]->getExitLevel());
    assertEquals("<", nextState->getRuleList()[2]->toString());
    assertTrue(nextState->getRuleList()[2]->isNested());

    // single line automatically transformed in multi line (since
    // one delimiter has more than one char)
    HighlightRulePtr singleToMultiRule = HighlightRulePtr(
            factory.createLineRule("foo", "<<", ">>", "\\\\"));

    cout << "single line rule (transformed): ";
    coutPrinter.printHighlightRule(singleToMultiRule.get());
    cout << endl;

    nextState = singleToMultiRule->getNextState().get();
    assertEquals(">>", nextState->getRuleList()[0]->toString());
    assertEquals(1, nextState->getRuleList()[0]->getExitLevel());

    // check state copy
    HighlightStatePtr stateCopy = HighlightStatePtr(
            new HighlightState(*nextState));
    // a new id must have been created for the copy
    assertEquals(nextState->getId()+1, stateCopy->getId());
    rule = HighlightRulePtr(factory.createSimpleRule("foo", "foo"));
    // change the second rule of the state
    HighlightRulePtr oldRule = stateCopy->replaceRule(0, rule);
    stateCopy->addRule(HighlightRulePtr(factory.createSimpleRule("foo", "bar")));

    cout << "orig state: ";
    coutPrinter.printHighlightState(nextState);
    cout << endl;

    cout << "copy state: ";
    coutPrinter.printHighlightState(stateCopy.get());
    cout << endl;

    // check that the original state is still the same
    assertEquals(">>", nextState->getRuleList()[0]->toString());
    assertEquals(1, nextState->getRuleList()[0]->getExitLevel());
    assertEquals(">>", oldRule->toString());
    assertEquals(1, oldRule->getExitLevel());

    // and that the new one has changed rules
    assertEquals("foo", stateCopy->getRuleList()[0]->toString());
    assertEquals(0, stateCopy->getRuleList()[0]->getExitLevel());
    assertEquals("bar", stateCopy->getRuleList()[2]->toString());

    // test for MatchingParameters (beginning of line)
    HighlightStatePtr stateWithBOL = HighlightStatePtr(new HighlightState);
    stateWithBOL->addRule(HighlightRulePtr(factory.createSimpleRule("BOL",
            "^[[:word:]]+")));
    stateWithBOL->addRule(HighlightRulePtr(factory.createSimpleRule("NOTBOL",
            "foo")));

    cout << "state with BOL: ";
    coutPrinter.printHighlightState(stateWithBOL.get());
    cout << endl;

    // the first rule matches since we're at the beginning of the line
    check_state(stateWithBOL.get(), params, "foo at the beginning", true,
            "foo", "", " at the beginning", "^[[:word:]]+", "BOL");

    // the second rule matches since we specified that we're not at the beginning of the line
    MatchingParameters paramsNotBOL;
    paramsNotBOL.beginningOfLine = false;
    check_state(stateWithBOL.get(), paramsNotBOL, "foo at the beginning", true,
            "foo", "", " at the beginning", "foo", "NOTBOL");

    // test for compound rules
    ElemNameList nameList;
    nameList.push_back("keyword");
    nameList.push_back("normal");
    nameList.push_back("type");
    HighlightRulePtr compoundRule = HighlightRulePtr(
            factory.createCompoundRule(nameList,
                    "(class)([[:blank:]]+)([[:word:]]+)"));

    cout << "compound rule: ";
    coutPrinter.printHighlightRule(compoundRule.get());
    cout << endl;

    MatchedElements expectedMatchedElements;
    expectedMatchedElements.push_back(make_pair("keyword", "class"));
    expectedMatchedElements.push_back(make_pair("normal", "  "));
    expectedMatchedElements.push_back(make_pair("type", "MyClass"));

    check_compound_regex(compoundRule.get(), params, "class  MyClass",
            expectedMatchedElements, "", "");

    // test for rules with no end (i.e., \z)
    rule = HighlightRulePtr(factory.createLineRule("foo", "#", "", "\\\\"));

    cout << "line rule: ";
    coutPrinter.printHighlightRule(rule.get());
    cout << endl;

    assertEquals("#", rule->toString());
    assertTrue(rule->getNextState().get());
    assertEquals("\\z", rule->getNextState()->getRuleList().front()->toString());

    check_regex(rule.get(), params, "before # after", true, "#", "before ",
            " after");

    // test for replacement
    rule = HighlightRulePtr(factory.createSimpleRule("foo", "@{2} @{1} @{3}"));
    ReplacementList rep(9);
    rep[0] = "first";
    rep[1] = "second";

    rule->replaceReferences(rep);

    cout << "replaced rule: " << rule->toString() << endl;

    assertEquals("second first ", rule->toString());

    // test replacement for states
    HighlightRulePtr origRep1 = HighlightRulePtr(factory.createSimpleRule(
            "foo", "@{2} @{1} @{3}"));
    HighlightRulePtr origNoRep = HighlightRulePtr(factory.createSimpleRule(
            "foo", "no @{1} replacement"));
    HighlightRulePtr origRep2 = HighlightRulePtr(factory.createSimpleRule(
            "foo", "@{3} @{1} @{2}"));

    origRep1->setNeedsReferenceReplacement();
    origRep2->setNeedsReferenceReplacement();

    HighlightStatePtr stateWithRepl = HighlightStatePtr(new HighlightState);

    stateWithRepl->addRule(origRep1);
    stateWithRepl->addRule(origNoRep);
    stateWithRepl->addRule(origRep2);

    stateWithRepl->replaceReferences(rep);

    coutPrinter.printHighlightState(stateWithRepl.get());

    // check that the original rule have not been changed
    assertEquals("@{2} @{1} @{3}", origRep1->toString());
    assertEquals("@{3} @{1} @{2}", origRep2->toString());

    // that the second rule was not changed
    assertEquals("no @{1} replacement",
            stateWithRepl->getRuleList()[1]->toString());

    // that the other two were changed
    assertEquals("second first ", stateWithRepl->getRuleList()[0]->toString());
    assertEquals(" first second", stateWithRepl->getRuleList()[2]->toString());

    // test for subexpressions
    rule = HighlightRulePtr(factory.createSimpleRule("foo",
            "(class) ([[:word:]]+) (\\{)"));
    rule->setHasSubexpressions();

    // the expected subexpressions
    MatchedSubExps subexps;
    subexps.push_back("class");
    subexps.push_back("foo");
    subexps.push_back("{");

    check_regex(rule.get(), params, "my class foo {", true, "class foo {",
            "my ", "", subexps);

    cout << "*** test_regexrules SUCCESS" << endl;

    return 0;
}