1 /*
2  *          Copyright Andrey Semashev 2007 - 2015.
3  * Distributed under the Boost Software License, Version 1.0.
4  *    (See accompanying file LICENSE_1_0.txt or copy at
5  *          http://www.boost.org/LICENSE_1_0.txt)
6  */
7 /*!
8  * \file   setup_filter_parser.cpp
9  * \author Andrey Semashev
10  * \date   24.08.2013
11  *
12  * \brief  This header contains tests for the filter parser.
13  */
14 
15 #define BOOST_TEST_MODULE setup_filter_parser
16 
17 #include <string>
18 #include <boost/test/unit_test.hpp>
19 #include <boost/log/utility/setup/filter_parser.hpp>
20 
21 #if !defined(BOOST_LOG_WITHOUT_SETTINGS_PARSERS) && !defined(BOOST_LOG_WITHOUT_DEFAULT_FACTORIES)
22 
23 #include <boost/smart_ptr/shared_ptr.hpp>
24 #include <boost/log/exceptions.hpp>
25 #include <boost/log/attributes/constant.hpp>
26 #include <boost/log/attributes/attribute_set.hpp>
27 #include <boost/log/attributes/attribute_value_set.hpp>
28 #include <boost/log/expressions/filter.hpp>
29 
30 namespace logging = boost::log;
31 namespace attrs = logging::attributes;
32 
33 typedef logging::attribute_set attr_set;
34 typedef logging::attribute_value_set attr_values;
35 
36 // Tests for attribute presence check
BOOST_AUTO_TEST_CASE(attr_presence)37 BOOST_AUTO_TEST_CASE(attr_presence)
38 {
39     attrs::constant< int > attr1(10);
40     attr_set set1, set2, set3;
41 
42     attr_values values1(set1, set2, set3);
43     values1.freeze();
44 
45     set1["MyAttr"] = attr1;
46     attr_values values2(set1, set2, set3);
47     values2.freeze();
48 
49     {
50         logging::filter f = logging::parse_filter("%MyAttr%");
51         BOOST_CHECK(!f(values1));
52         BOOST_CHECK(f(values2));
53     }
54     {
55         logging::filter f = logging::parse_filter(" % MyAttr % ");
56         BOOST_CHECK(!f(values1));
57         BOOST_CHECK(f(values2));
58     }
59 }
60 
61 // Tests for integer relation filter
BOOST_AUTO_TEST_CASE(int_relation)62 BOOST_AUTO_TEST_CASE(int_relation)
63 {
64     attrs::constant< int > attr1(10);
65     attrs::constant< long > attr2(20);
66     attrs::constant< int > attr3(-2);
67     attr_set set1, set2, set3;
68 
69     attr_values values1(set1, set2, set3);
70     values1.freeze();
71 
72     set1["MyAttr"] = attr1;
73     attr_values values2(set1, set2, set3);
74     values2.freeze();
75 
76     set1["MyAttr"] = attr2;
77     attr_values values3(set1, set2, set3);
78     values3.freeze();
79 
80     set1["MyAttr"] = attr3;
81     attr_values values4(set1, set2, set3);
82     values4.freeze();
83 
84     {
85         logging::filter f = logging::parse_filter("%MyAttr% = 10");
86         BOOST_CHECK(!f(values1));
87         BOOST_CHECK(f(values2));
88         BOOST_CHECK(!f(values3));
89         BOOST_CHECK(!f(values4));
90     }
91     {
92         logging::filter f = logging::parse_filter("%MyAttr% != 10");
93         BOOST_CHECK(!f(values1));
94         BOOST_CHECK(!f(values2));
95         BOOST_CHECK(f(values3));
96         BOOST_CHECK(f(values4));
97     }
98     {
99         logging::filter f = logging::parse_filter("%MyAttr% < 20");
100         BOOST_CHECK(!f(values1));
101         BOOST_CHECK(f(values2));
102         BOOST_CHECK(!f(values3));
103         BOOST_CHECK(f(values4));
104     }
105     {
106         logging::filter f = logging::parse_filter("%MyAttr% < -7");
107         BOOST_CHECK(!f(values1));
108         BOOST_CHECK(!f(values2));
109         BOOST_CHECK(!f(values3));
110         BOOST_CHECK(!f(values4));
111     }
112     {
113         logging::filter f = logging::parse_filter("%MyAttr% > 10");
114         BOOST_CHECK(!f(values1));
115         BOOST_CHECK(!f(values2));
116         BOOST_CHECK(f(values3));
117         BOOST_CHECK(!f(values4));
118     }
119     {
120         logging::filter f = logging::parse_filter("%MyAttr% > -5");
121         BOOST_CHECK(!f(values1));
122         BOOST_CHECK(f(values2));
123         BOOST_CHECK(f(values3));
124         BOOST_CHECK(f(values4));
125     }
126     {
127         logging::filter f = logging::parse_filter("%MyAttr% <= 20");
128         BOOST_CHECK(!f(values1));
129         BOOST_CHECK(f(values2));
130         BOOST_CHECK(f(values3));
131         BOOST_CHECK(f(values4));
132     }
133     {
134         logging::filter f = logging::parse_filter("%MyAttr% >= 20");
135         BOOST_CHECK(!f(values1));
136         BOOST_CHECK(!f(values2));
137         BOOST_CHECK(f(values3));
138         BOOST_CHECK(!f(values4));
139     }
140 }
141 
142 // Tests for floating point relation filter
BOOST_AUTO_TEST_CASE(fp_relation)143 BOOST_AUTO_TEST_CASE(fp_relation)
144 {
145     attrs::constant< float > attr1(2.5f);
146     attrs::constant< float > attr2(8.8f);
147     attrs::constant< double > attr3(-9.1);
148     attrs::constant< float > attr4(0.0f);
149     attr_set set1, set2, set3;
150 
151     attr_values values1(set1, set2, set3);
152     values1.freeze();
153 
154     set1["MyAttr"] = attr1;
155     attr_values values2(set1, set2, set3);
156     values2.freeze();
157 
158     set1["MyAttr"] = attr2;
159     attr_values values3(set1, set2, set3);
160     values3.freeze();
161 
162     set1["MyAttr"] = attr3;
163     attr_values values4(set1, set2, set3);
164     values4.freeze();
165 
166     set1["MyAttr"] = attr4;
167     attr_values values5(set1, set2, set3);
168     values5.freeze();
169 
170     {
171         logging::filter f = logging::parse_filter("%MyAttr% = 10.3");
172         BOOST_CHECK(!f(values1));
173         BOOST_CHECK(!f(values2));
174         BOOST_CHECK(!f(values3));
175         BOOST_CHECK(!f(values4));
176         BOOST_CHECK(!f(values5));
177     }
178     {
179         logging::filter f = logging::parse_filter("%MyAttr% != 10");
180         BOOST_CHECK(!f(values1));
181         BOOST_CHECK(f(values2));
182         BOOST_CHECK(f(values3));
183         BOOST_CHECK(f(values4));
184         BOOST_CHECK(f(values5));
185     }
186     {
187         logging::filter f = logging::parse_filter("%MyAttr% < 5.5");
188         BOOST_CHECK(!f(values1));
189         BOOST_CHECK(f(values2));
190         BOOST_CHECK(!f(values3));
191         BOOST_CHECK(f(values4));
192         BOOST_CHECK(f(values5));
193     }
194     {
195         logging::filter f = logging::parse_filter("%MyAttr% < -7");
196         BOOST_CHECK(!f(values1));
197         BOOST_CHECK(!f(values2));
198         BOOST_CHECK(!f(values3));
199         BOOST_CHECK(f(values4));
200         BOOST_CHECK(!f(values5));
201     }
202     {
203         logging::filter f = logging::parse_filter("%MyAttr% > 5.6");
204         BOOST_CHECK(!f(values1));
205         BOOST_CHECK(!f(values2));
206         BOOST_CHECK(f(values3));
207         BOOST_CHECK(!f(values4));
208         BOOST_CHECK(!f(values5));
209     }
210     {
211         logging::filter f = logging::parse_filter("%MyAttr% > -5");
212         BOOST_CHECK(!f(values1));
213         BOOST_CHECK(f(values2));
214         BOOST_CHECK(f(values3));
215         BOOST_CHECK(!f(values4));
216         BOOST_CHECK(f(values5));
217     }
218     {
219         logging::filter f = logging::parse_filter("%MyAttr% <= 20");
220         BOOST_CHECK(!f(values1));
221         BOOST_CHECK(f(values2));
222         BOOST_CHECK(f(values3));
223         BOOST_CHECK(f(values4));
224         BOOST_CHECK(f(values5));
225     }
226     {
227         logging::filter f = logging::parse_filter("%MyAttr% >= 20");
228         BOOST_CHECK(!f(values1));
229         BOOST_CHECK(!f(values2));
230         BOOST_CHECK(!f(values3));
231         BOOST_CHECK(!f(values4));
232         BOOST_CHECK(!f(values5));
233     }
234 }
235 
236 // Tests for string relation filter
BOOST_AUTO_TEST_CASE(string_relation)237 BOOST_AUTO_TEST_CASE(string_relation)
238 {
239     attrs::constant< std::string > attr1("hello");
240     attr_set set1, set2, set3;
241 
242     attr_values values1(set1, set2, set3);
243     values1.freeze();
244 
245     set1["MyStr"] = attr1;
246     attr_values values2(set1, set2, set3);
247     values2.freeze();
248 
249     {
250         logging::filter f = logging::parse_filter("%MyStr% = hello");
251         BOOST_CHECK(!f(values1));
252         BOOST_CHECK(f(values2));
253     }
254     {
255         logging::filter f = logging::parse_filter("%MyStr% = \"hello\"");
256         BOOST_CHECK(!f(values1));
257         BOOST_CHECK(f(values2));
258     }
259     {
260         logging::filter f = logging::parse_filter(" % MyStr % = \"hello\" ");
261         BOOST_CHECK(!f(values1));
262         BOOST_CHECK(f(values2));
263     }
264     {
265         logging::filter f = logging::parse_filter("%MyStr% = \" hello\"");
266         BOOST_CHECK(!f(values1));
267         BOOST_CHECK(!f(values2));
268     }
269     {
270         logging::filter f = logging::parse_filter("%MyStr% = \"hello \"");
271         BOOST_CHECK(!f(values1));
272         BOOST_CHECK(!f(values2));
273     }
274     {
275         logging::filter f = logging::parse_filter("%MyStr% = \"world\"");
276         BOOST_CHECK(!f(values1));
277         BOOST_CHECK(!f(values2));
278     }
279     {
280         logging::filter f = logging::parse_filter("%MyStr% = \"Hello\"");
281         BOOST_CHECK(!f(values1));
282         BOOST_CHECK(!f(values2));
283     }
284     {
285         logging::filter f = logging::parse_filter("%MyStr% != hello");
286         BOOST_CHECK(!f(values1));
287         BOOST_CHECK(!f(values2));
288     }
289     {
290         logging::filter f = logging::parse_filter("%MyStr% != world");
291         BOOST_CHECK(!f(values1));
292         BOOST_CHECK(f(values2));
293     }
294     {
295         logging::filter f = logging::parse_filter("%MyStr% < world");
296         BOOST_CHECK(!f(values1));
297         BOOST_CHECK(f(values2));
298     }
299     {
300         logging::filter f = logging::parse_filter("%MyStr% > world");
301         BOOST_CHECK(!f(values1));
302         BOOST_CHECK(!f(values2));
303     }
304 
305     // Check that strings that look like numbers can still be used in filters
306     attrs::constant< std::string > attr2("55");
307     set1["MyStr"] = attr2;
308     attr_values values3(set1, set2, set3);
309     values3.freeze();
310 
311     {
312         logging::filter f = logging::parse_filter("%MyStr% = \"55\"");
313         BOOST_CHECK(f(values3));
314     }
315     {
316         logging::filter f = logging::parse_filter("%MyStr% < \"555\"");
317         BOOST_CHECK(f(values3));
318     }
319     {
320         logging::filter f = logging::parse_filter("%MyStr% > \"44\"");
321         BOOST_CHECK(f(values3));
322     }
323 }
324 
325 // Tests for multiple expression filter
BOOST_AUTO_TEST_CASE(multi_expression)326 BOOST_AUTO_TEST_CASE(multi_expression)
327 {
328     attrs::constant< int > attr1(10);
329     attrs::constant< int > attr2(20);
330     attrs::constant< std::string > attr3("hello");
331     attrs::constant< std::string > attr4("world");
332     attr_set set1, set2, set3;
333 
334     attr_values values1(set1, set2, set3);
335     values1.freeze();
336 
337     set1["MyAttr"] = attr1;
338     attr_values values2(set1, set2, set3);
339     values2.freeze();
340 
341     set1["MyAttr"] = attr2;
342     attr_values values3(set1, set2, set3);
343     values3.freeze();
344 
345     set1["MyStr"] = attr3;
346     attr_values values4(set1, set2, set3);
347     values4.freeze();
348 
349     set1["MyStr"] = attr4;
350     attr_values values5(set1, set2, set3);
351     values5.freeze();
352 
353     {
354         logging::filter f = logging::parse_filter("%MyAttr% = 10 & %MyStr% = \"hello\"");
355         BOOST_CHECK(!f(values1));
356         BOOST_CHECK(!f(values2));
357         BOOST_CHECK(!f(values3));
358         BOOST_CHECK(!f(values4));
359         BOOST_CHECK(!f(values5));
360     }
361     {
362         logging::filter f = logging::parse_filter("%MyAttr% > 10 & %MyStr% = \"hello\"");
363         BOOST_CHECK(!f(values1));
364         BOOST_CHECK(!f(values2));
365         BOOST_CHECK(!f(values3));
366         BOOST_CHECK(f(values4));
367         BOOST_CHECK(!f(values5));
368     }
369     {
370         logging::filter f = logging::parse_filter("%MyAttr% > 10 and %MyStr% = \"hello\"");
371         BOOST_CHECK(!f(values1));
372         BOOST_CHECK(!f(values2));
373         BOOST_CHECK(!f(values3));
374         BOOST_CHECK(f(values4));
375         BOOST_CHECK(!f(values5));
376     }
377     {
378         logging::filter f = logging::parse_filter("%MyAttr% = 10 | %MyStr% = \"world\"");
379         BOOST_CHECK(!f(values1));
380         BOOST_CHECK(f(values2));
381         BOOST_CHECK(!f(values3));
382         BOOST_CHECK(!f(values4));
383         BOOST_CHECK(f(values5));
384     }
385     {
386         logging::filter f = logging::parse_filter("%MyAttr% > 10 | %MyStr% = \"world\"");
387         BOOST_CHECK(!f(values1));
388         BOOST_CHECK(!f(values2));
389         BOOST_CHECK(f(values3));
390         BOOST_CHECK(f(values4));
391         BOOST_CHECK(f(values5));
392     }
393     {
394         logging::filter f = logging::parse_filter("%MyAttr% = 10 or %MyStr% = \"world\"");
395         BOOST_CHECK(!f(values1));
396         BOOST_CHECK(f(values2));
397         BOOST_CHECK(!f(values3));
398         BOOST_CHECK(!f(values4));
399         BOOST_CHECK(f(values5));
400     }
401     {
402         logging::filter f = logging::parse_filter("%MyAttr% > 0 & %MyAttr% < 20 | %MyStr% = \"hello\"");
403         BOOST_CHECK(!f(values1));
404         BOOST_CHECK(f(values2));
405         BOOST_CHECK(!f(values3));
406         BOOST_CHECK(f(values4));
407         BOOST_CHECK(!f(values5));
408     }
409 }
410 
411 // Tests for negation
BOOST_AUTO_TEST_CASE(negation)412 BOOST_AUTO_TEST_CASE(negation)
413 {
414     attrs::constant< int > attr1(10);
415     attrs::constant< int > attr2(20);
416     attrs::constant< std::string > attr3("hello");
417     attr_set set1, set2, set3;
418 
419     attr_values values1(set1, set2, set3);
420     values1.freeze();
421 
422     set1["MyAttr"] = attr1;
423     attr_values values2(set1, set2, set3);
424     values2.freeze();
425 
426     set1["MyAttr"] = attr2;
427     attr_values values3(set1, set2, set3);
428     values3.freeze();
429 
430     set1["MyStr"] = attr3;
431     attr_values values4(set1, set2, set3);
432     values4.freeze();
433 
434     // Test with presence filter
435     {
436         logging::filter f = logging::parse_filter("!%MyAttr%");
437         BOOST_CHECK(f(values1));
438         BOOST_CHECK(!f(values2));
439     }
440     {
441         logging::filter f = logging::parse_filter(" ! % MyAttr % ");
442         BOOST_CHECK(f(values1));
443         BOOST_CHECK(!f(values2));
444     }
445     {
446         logging::filter f = logging::parse_filter("not %MyAttr%");
447         BOOST_CHECK(f(values1));
448         BOOST_CHECK(!f(values2));
449     }
450     {
451         logging::filter f = logging::parse_filter("!!%MyAttr%");
452         BOOST_CHECK(!f(values1));
453         BOOST_CHECK(f(values2));
454     }
455 
456     // Test with relations
457     {
458         logging::filter f = logging::parse_filter("!(%MyAttr% = 10)");
459         BOOST_CHECK(f(values1));
460         BOOST_CHECK(!f(values2));
461         BOOST_CHECK(f(values3));
462     }
463     {
464         logging::filter f = logging::parse_filter("not ( %MyAttr% = 10 ) ");
465         BOOST_CHECK(f(values1));
466         BOOST_CHECK(!f(values2));
467         BOOST_CHECK(f(values3));
468     }
469     {
470         logging::filter f = logging::parse_filter("!(%MyAttr% < 20)");
471         BOOST_CHECK(f(values1));
472         BOOST_CHECK(!f(values2));
473         BOOST_CHECK(f(values3));
474     }
475 
476     // Test with multiple subexpressions
477     {
478         logging::filter f = logging::parse_filter("!(%MyAttr% = 20 & %MyStr% = hello)");
479         BOOST_CHECK(f(values1));
480         BOOST_CHECK(f(values2));
481         BOOST_CHECK(f(values3));
482         BOOST_CHECK(!f(values4));
483     }
484     {
485         logging::filter f = logging::parse_filter("!(%MyAttr% = 10 | %MyStr% = hello)");
486         BOOST_CHECK(f(values1));
487         BOOST_CHECK(!f(values2));
488         BOOST_CHECK(f(values3));
489         BOOST_CHECK(!f(values4));
490     }
491 }
492 
493 // Tests for begins_with relation filter
BOOST_AUTO_TEST_CASE(begins_with_relation)494 BOOST_AUTO_TEST_CASE(begins_with_relation)
495 {
496     attrs::constant< std::string > attr1("abcdABCD");
497     attr_set set1, set2, set3;
498 
499     set1["MyStr"] = attr1;
500     attr_values values1(set1, set2, set3);
501     values1.freeze();
502 
503     {
504         logging::filter f = logging::parse_filter("%MyStr% begins_with \"abcd\"");
505         BOOST_CHECK(f(values1));
506     }
507     {
508         logging::filter f = logging::parse_filter("%MyStr% begins_with \"ABCD\"");
509         BOOST_CHECK(!f(values1));
510     }
511     {
512         logging::filter f = logging::parse_filter("%MyStr% begins_with \"efgh\"");
513         BOOST_CHECK(!f(values1));
514     }
515 }
516 
517 // Tests for ends_with relation filter
BOOST_AUTO_TEST_CASE(ends_with_relation)518 BOOST_AUTO_TEST_CASE(ends_with_relation)
519 {
520     attrs::constant< std::string > attr1("abcdABCD");
521     attr_set set1, set2, set3;
522 
523     set1["MyStr"] = attr1;
524     attr_values values1(set1, set2, set3);
525     values1.freeze();
526 
527     {
528         logging::filter f = logging::parse_filter("%MyStr% ends_with \"abcd\"");
529         BOOST_CHECK(!f(values1));
530     }
531     {
532         logging::filter f = logging::parse_filter("%MyStr% ends_with \"ABCD\"");
533         BOOST_CHECK(f(values1));
534     }
535     {
536         logging::filter f = logging::parse_filter("%MyStr% ends_with \"efgh\"");
537         BOOST_CHECK(!f(values1));
538     }
539 }
540 
541 // Tests for contains relation filter
BOOST_AUTO_TEST_CASE(contains_relation)542 BOOST_AUTO_TEST_CASE(contains_relation)
543 {
544     attrs::constant< std::string > attr1("abcdABCD");
545     attr_set set1, set2, set3;
546 
547     set1["MyStr"] = attr1;
548     attr_values values1(set1, set2, set3);
549     values1.freeze();
550 
551     {
552         logging::filter f = logging::parse_filter("%MyStr% contains \"abcd\"");
553         BOOST_CHECK(f(values1));
554     }
555     {
556         logging::filter f = logging::parse_filter("%MyStr% contains \"ABCD\"");
557         BOOST_CHECK(f(values1));
558     }
559     {
560         logging::filter f = logging::parse_filter("%MyStr% contains \"cdAB\"");
561         BOOST_CHECK(f(values1));
562     }
563     {
564         logging::filter f = logging::parse_filter("%MyStr% contains \"efgh\"");
565         BOOST_CHECK(!f(values1));
566     }
567 }
568 
569 // Tests for regex matching relation filter
BOOST_AUTO_TEST_CASE(matches_relation)570 BOOST_AUTO_TEST_CASE(matches_relation)
571 {
572     attrs::constant< std::string > attr1("hello");
573     attrs::constant< std::string > attr2("127.0.0.1");
574     attr_set set1, set2, set3;
575 
576     set1["MyStr"] = attr1;
577     set1["MyIP"] = attr2;
578     attr_values values1(set1, set2, set3);
579     values1.freeze();
580 
581     {
582         logging::filter f = logging::parse_filter("%MyStr% matches \"h.*\"");
583         BOOST_CHECK(f(values1));
584     }
585     {
586         logging::filter f = logging::parse_filter("%MyStr% matches \"w.*\"");
587         BOOST_CHECK(!f(values1));
588     }
589     {
590         logging::filter f = logging::parse_filter("%MyStr% matches \"\\\\d*\"");
591         BOOST_CHECK(!f(values1));
592     }
593     {
594         logging::filter f = logging::parse_filter("%MyStr% matches \"[a-z]*\"");
595         BOOST_CHECK(f(values1));
596     }
597     {
598         logging::filter f = logging::parse_filter("%MyIP% matches \"\\\\d*\\\\.\\\\d*\\\\.\\\\d*\\\\.\\\\d*\"");
599         BOOST_CHECK(f(values1));
600     }
601 }
602 
603 namespace {
604 
605 class test_filter_factory :
606     public logging::filter_factory< char >
607 {
608 private:
609     typedef logging::filter_factory< char > base_type;
610 
611 public:
612     enum relation_type
613     {
614         custom,
615         exists,
616         equality,
617         inequality,
618         less,
619         greater,
620         less_or_equal,
621         greater_or_equal
622     };
623 
624     typedef base_type::string_type string_type;
625 
626 public:
test_filter_factory(logging::attribute_name const & name)627     explicit test_filter_factory(logging::attribute_name const& name) : m_name(name), m_rel(custom), m_called(false)
628     {
629     }
630 
expect_relation(relation_type rel,string_type const & arg)631     void expect_relation(relation_type rel, string_type const& arg)
632     {
633         m_rel = rel;
634         m_arg = arg;
635         m_custom_rel.clear();
636     }
637 
expect_relation(string_type const & rel,string_type const & arg)638     void expect_relation(string_type const& rel, string_type const& arg)
639     {
640         m_rel = custom;
641         m_arg = arg;
642         m_custom_rel = rel;
643     }
644 
check_called()645     void check_called()
646     {
647         BOOST_CHECK(m_called);
648         m_called = false;
649     }
650 
on_exists_test(logging::attribute_name const & name)651     logging::filter on_exists_test(logging::attribute_name const& name)
652     {
653         BOOST_CHECK_EQUAL(m_name, name);
654         BOOST_CHECK_EQUAL(m_rel, exists);
655         m_called = true;
656         return logging::filter();
657     }
on_equality_relation(logging::attribute_name const & name,string_type const & arg)658     logging::filter on_equality_relation(logging::attribute_name const& name, string_type const& arg)
659     {
660         BOOST_CHECK_EQUAL(m_name, name);
661         BOOST_CHECK_EQUAL(m_rel, equality);
662         BOOST_CHECK_EQUAL(m_arg, arg);
663         m_called = true;
664         return logging::filter();
665     }
on_inequality_relation(logging::attribute_name const & name,string_type const & arg)666     logging::filter on_inequality_relation(logging::attribute_name const& name, string_type const& arg)
667     {
668         BOOST_CHECK_EQUAL(m_name, name);
669         BOOST_CHECK_EQUAL(m_rel, inequality);
670         BOOST_CHECK_EQUAL(m_arg, arg);
671         m_called = true;
672         return logging::filter();
673     }
on_less_relation(logging::attribute_name const & name,string_type const & arg)674     logging::filter on_less_relation(logging::attribute_name const& name, string_type const& arg)
675     {
676         BOOST_CHECK_EQUAL(m_name, name);
677         BOOST_CHECK_EQUAL(m_rel, less);
678         BOOST_CHECK_EQUAL(m_arg, arg);
679         m_called = true;
680         return logging::filter();
681     }
on_greater_relation(logging::attribute_name const & name,string_type const & arg)682     logging::filter on_greater_relation(logging::attribute_name const& name, string_type const& arg)
683     {
684         BOOST_CHECK_EQUAL(m_name, name);
685         BOOST_CHECK_EQUAL(m_rel, greater);
686         BOOST_CHECK_EQUAL(m_arg, arg);
687         m_called = true;
688         return logging::filter();
689     }
on_less_or_equal_relation(logging::attribute_name const & name,string_type const & arg)690     logging::filter on_less_or_equal_relation(logging::attribute_name const& name, string_type const& arg)
691     {
692         BOOST_CHECK_EQUAL(m_name, name);
693         BOOST_CHECK_EQUAL(m_rel, less_or_equal);
694         BOOST_CHECK_EQUAL(m_arg, arg);
695         m_called = true;
696         return logging::filter();
697     }
on_greater_or_equal_relation(logging::attribute_name const & name,string_type const & arg)698     logging::filter on_greater_or_equal_relation(logging::attribute_name const& name, string_type const& arg)
699     {
700         BOOST_CHECK_EQUAL(m_name, name);
701         BOOST_CHECK_EQUAL(m_rel, greater_or_equal);
702         BOOST_CHECK_EQUAL(m_arg, arg);
703         m_called = true;
704         return logging::filter();
705     }
on_custom_relation(logging::attribute_name const & name,string_type const & rel,string_type const & arg)706     logging::filter on_custom_relation(logging::attribute_name const& name, string_type const& rel, string_type const& arg)
707     {
708         BOOST_CHECK_EQUAL(m_name, name);
709         BOOST_CHECK_EQUAL(m_rel, custom);
710         BOOST_CHECK_EQUAL(m_custom_rel, rel);
711         BOOST_CHECK_EQUAL(m_arg, arg);
712         m_called = true;
713         return logging::filter();
714     }
715 
716 private:
717     logging::attribute_name m_name;
718     relation_type m_rel;
719     string_type m_arg;
720     string_type m_custom_rel;
721     bool m_called;
722 };
723 
724 } // namespace
725 
726 // Tests for filter factory
BOOST_AUTO_TEST_CASE(filter_factory)727 BOOST_AUTO_TEST_CASE(filter_factory)
728 {
729     logging::attribute_name attr_name("MyCustomAttr");
730     boost::shared_ptr< test_filter_factory > factory(new test_filter_factory(attr_name));
731     logging::register_filter_factory(attr_name, factory);
732 
733     BOOST_TEST_CHECKPOINT("filter_factory::exists");
734     factory->expect_relation(test_filter_factory::exists, "");
735     logging::parse_filter("%MyCustomAttr%");
736     factory->check_called();
737 
738     BOOST_TEST_CHECKPOINT("filter_factory::equality");
739     factory->expect_relation(test_filter_factory::equality, "15");
740     logging::parse_filter("%MyCustomAttr% = 15");
741     factory->check_called();
742 
743     BOOST_TEST_CHECKPOINT("filter_factory::equality");
744     factory->expect_relation(test_filter_factory::equality, "hello");
745     logging::parse_filter("%MyCustomAttr% = hello");
746     factory->check_called();
747 
748     BOOST_TEST_CHECKPOINT("filter_factory::equality");
749     factory->expect_relation(test_filter_factory::equality, "hello");
750     logging::parse_filter("%MyCustomAttr% = \"hello\"");
751     factory->check_called();
752 
753     BOOST_TEST_CHECKPOINT("filter_factory::equality");
754     factory->expect_relation(test_filter_factory::equality, "hello\nworld");
755     logging::parse_filter("%MyCustomAttr% = \"hello\\nworld\"");
756     factory->check_called();
757 
758     BOOST_TEST_CHECKPOINT("filter_factory::inequality");
759     factory->expect_relation(test_filter_factory::inequality, "hello");
760     logging::parse_filter("%MyCustomAttr% != \"hello\"");
761     factory->check_called();
762 
763     BOOST_TEST_CHECKPOINT("filter_factory::less");
764     factory->expect_relation(test_filter_factory::less, "hello");
765     logging::parse_filter("%MyCustomAttr% < \"hello\"");
766     factory->check_called();
767 
768     BOOST_TEST_CHECKPOINT("filter_factory::greater");
769     factory->expect_relation(test_filter_factory::greater, "hello");
770     logging::parse_filter("%MyCustomAttr% > \"hello\"");
771     factory->check_called();
772 
773     BOOST_TEST_CHECKPOINT("filter_factory::less_or_equal");
774     factory->expect_relation(test_filter_factory::less_or_equal, "hello");
775     logging::parse_filter("%MyCustomAttr% <= \"hello\"");
776     factory->check_called();
777 
778     BOOST_TEST_CHECKPOINT("filter_factory::greater_or_equal");
779     factory->expect_relation(test_filter_factory::greater_or_equal, "hello");
780     logging::parse_filter("%MyCustomAttr% >= \"hello\"");
781     factory->check_called();
782 
783     BOOST_TEST_CHECKPOINT("filter_factory::custom");
784     factory->expect_relation("my_relation", "hello");
785     logging::parse_filter("%MyCustomAttr% my_relation \"hello\"");
786     factory->check_called();
787 }
788 
789 // Tests for invalid filters
BOOST_AUTO_TEST_CASE(invalid)790 BOOST_AUTO_TEST_CASE(invalid)
791 {
792     BOOST_CHECK_THROW(logging::parse_filter("%MyStr"), logging::parse_error);
793     BOOST_CHECK_THROW(logging::parse_filter("MyStr%"), logging::parse_error);
794     BOOST_CHECK_THROW(logging::parse_filter("%MyStr% abcd"), logging::parse_error);
795     BOOST_CHECK_THROW(logging::parse_filter("(%MyStr%"), logging::parse_error);
796     BOOST_CHECK_THROW(logging::parse_filter("%MyStr%)"), logging::parse_error);
797     BOOST_CHECK_THROW(logging::parse_filter("%%"), logging::parse_error);
798     BOOST_CHECK_THROW(logging::parse_filter("%"), logging::parse_error);
799     BOOST_CHECK_THROW(logging::parse_filter("!"), logging::parse_error);
800     BOOST_CHECK_THROW(logging::parse_filter("!()"), logging::parse_error);
801     BOOST_CHECK_THROW(logging::parse_filter("\"xxx\" == %MyStr%"), logging::parse_error);
802     BOOST_CHECK_THROW(logging::parse_filter("%MyStr% == \"xxx"), logging::parse_error);
803     BOOST_CHECK_THROW(logging::parse_filter("%MyStr% === \"xxx\""), logging::parse_error);
804     BOOST_CHECK_THROW(logging::parse_filter("%MyStr% ! \"xxx\""), logging::parse_error);
805     BOOST_CHECK_THROW(logging::parse_filter("%MyStr% %MyStr2%"), logging::parse_error);
806 }
807 
808 #endif // !defined(BOOST_LOG_WITHOUT_SETTINGS_PARSERS) && !defined(BOOST_LOG_WITHOUT_DEFAULT_FACTORIES)
809