+ Fixed the uber scanner test yet again (this time wrt

NULL characters embedded in the token strings).
+ Added a number of sniffing tests. The rules returned
  by the parser appear to sniff properly now.

Incidentally, our sniffer supports conjunctions, i.e the rule

1.0 ('abc') [9] ('xyz')

is equivalent to the rule

1.0 ('abc______xyz' & 0xFFF000000FFF)

This is different than the R5 sniffer, which doesn't reject
rules like the former, but appears to ignore all expressions
in the rule except for the first, i.e. it would treat the first
rule as

1.0 ('abc')

The only problem I can see with this is if someone for
some reason wrote such a rule with multiple expressions
for use with the R5 sniffer. It would likely work differently
with ours. I'm going to search my MIME database and see
if any such rules exist. If so, it'll be easy to switch to the
R5 way of doing things.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@663 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Tyler Dauwalder 2002-08-09 10:38:30 +00:00
parent fe70cd16af
commit b657eab3cf
2 changed files with 265 additions and 4 deletions

View File

@ -4,12 +4,15 @@
#include <cppunit/Test.h> #include <cppunit/Test.h>
#include <cppunit/TestSuite.h> #include <cppunit/TestSuite.h>
#include <cppunit/TestCaller.h> #include <cppunit/TestCaller.h>
#include <sniffer/Rule.h>
#include <sniffer/Parser.h> #include <sniffer/Parser.h>
#include <DataIO.h>
#include <Mime.h> #include <Mime.h>
#include <String.h> // BString #include <String.h> // BString
#include <TestUtils.h> #include <TestUtils.h>
#include <stdio.h> #include <stdio.h>
#include <string>
using namespace Sniffer; using namespace Sniffer;
@ -23,6 +26,8 @@ MimeSnifferTest::Suite() {
&MimeSnifferTest::ScannerTest) ); &MimeSnifferTest::ScannerTest) );
suite->addTest( new TC("Mime Sniffer::Parser Test", suite->addTest( new TC("Mime Sniffer::Parser Test",
&MimeSnifferTest::ParserTest) ); &MimeSnifferTest::ParserTest) );
suite->addTest( new TC("Mime Sniffer::Sniffer Test",
&MimeSnifferTest::SnifferTest) );
return suite; return suite;
} }
@ -718,12 +723,12 @@ MimeSnifferTest::ScannerTest() {
F(-1.0e1), F(-2.0e-2), F(-3.0e3), F(1.0e1), F(2.0e-2), F(3.0e3), F(-1.0e1), F(-2.0e-2), F(-3.0e3), F(1.0e1), F(2.0e-2), F(3.0e3),
F(0.012345), F(1.23456), T(LeftParen), T(RightParen), T(LeftBracket), F(0.012345), F(1.23456), T(LeftParen), T(RightParen), T(LeftBracket),
T(RightBracket), T(Divider), T(Ampersand), T(Colon), T(RightBracket), T(Divider), T(Ampersand), T(Colon),
S("abcxyzABCXYZ_ ( ) [ ] | & : \t\n \" ' \012\0\377\x00\x12\xab\xCD\xeF\x1A\xb2 "), S(std::string("abcxyzABCXYZ_ ( ) [ ] | & : \t\n \" ' \012\0\377\x00\x12\xab\xCD\xeF\x1A\xb2 ", 46)),
S("abcxyzABCXYZ_ ( ) [ ] | & : \t\n \" ' \012\0\377\x00\x12\xab\xCD\xeF\x1A\xb2 "), S(std::string("abcxyzABCXYZ_ ( ) [ ] | & : \t\n \" ' \012\0\377\x00\x12\xab\xCD\xeF\x1A\xb2 ", 46)),
S("\000abc_xyz123"), S(std::string("\000abc_xyz123", 11)),
S("\241a1"), S("\241a1"),
S("!?\\"), S("!?\\"),
S("\x00"), S("\x12"), S("\xAB\xCD"), S("\xAB\xCD"), S(std::string("\x00", 1)), S("\x12"), S("\xAB\xCD"), S("\xAB\xCD"),
S("\x01\x23\x45\x67\x89\xAB\xCD\xEF\xFE\xDC\xBA") S("\x01\x23\x45\x67\x89\xAB\xCD\xEF\xFE\xDC\xBA")
} }
}, },
@ -1081,3 +1086,258 @@ MimeSnifferTest::ParserTest() {
} }
} }
} }
void dumpStr(const std::string &string, const char *label = NULL) {
if (label)
printf("%s: ", label);
for (int i = 0; i < string.length(); i++)
printf("%x ", string[i]);
printf("\n");
}
void
MimeSnifferTest::SnifferTest() {
#if TEST_R5
Outputf("(no tests actually performed for R5 version)\n");
#else // TEST_R5
const char *rules[] = {
// General tests
"1.0 ('#include')",
"0.0 [0:32] ('#include')",
"0.e-230 [0:32] (\\#include | \\#ifndef)",
".2 ([0:32] \"#include\" | [0] '#define' | [0:200] 'int main(')",
"1.0 [0:32] ('<html>' | '<head>' | '<body>')",
// Range tests
"1.0 [0:9] ('rock')",
"1.0 ([0:9] 'roll')",
"1.0 ([0:9] 'rock' | [0:9] 'roll')",
"1.0 [0:9] ('rock' | 'roll')",
"1.0 ([0] 'rock')",
"1.0 ([0] 'rock' | [0:9] 'roll')",
"1.0 ([9] 'rock' | [10] 'roll')",
// Mask, octal, and hex tests
"1.0 (\\xFF\\xFF & '\\xF0\\xF0')",
"1.0 ('\\33\\34' & \\xFF\\x00)",
"1.0 (\\33\\34 & \"\\x00\\xFF\")",
"1.0 (\\xFF & \\x05)",
// Conjunctions
"1.0 ([4] 'rock') ([9] 'roll')",
"1.0 [5] ('roll') [10] ('rock')",
"1.0 [4] ('rock' | 'roll') ([9] 'rock' | [10] 'roll')",
};
const int ruleCount = sizeof(rules)/sizeof(char*);
struct test_case {
const std::string data;
const bool result[ruleCount];
} tests[] = {
//------------------------------
{
"#include <stdio.h> \n\
#include <stdlib.h> \n\
\n\
int main() { \n\
return 0; \n\
} \n\
\n\
", { true, true, true, true, false,
false, false, false, false, false, false, false,
false, false, false, false,
false, false, false
}
},
//------------------------------
{
" #include <stdio.h> \n\
#include <stdlib.h> \n\
\n\
int main() { \n\
return 0; \n\
} \n\
\n\
", { false, true, true, true, false,
false, false, false, false, false, false, false,
false, false, false, false,
false, false, false
}
},
//------------------------------
{
"#ifndef SOME_TEST_H \n\
#define SOME_TEST_H \n\
\n\
void main(); \n\
\n\
#endif // SOME_TEST_H \n\
\n\
", { false, false, true, false, false,
false, false, false, false, false, false, false,
false, false, false, false,
false, false, false
}
},
//------------------------------
{
"//------------------ \n\
// SomeTest.cpp \n\
//------------------ \n\
#include <stdio.h> \n\
\n\
int main() { \n\
return 0; \n\
} \n\
\n\
", { false, false, false, true, false,
false, false, false, false, false, false, false,
false, false, false, true,
// ^^^^ <= coincedence
false, false, false
}
},
//------------------------------
{
"<html> \n\
<body bgcolor='#ffffff'> \n\
HTML is boring as hell <br> \n\
when i write it too much <br> \n\
my head starts to swell <br> \n\
<br> \n\
HTML is stupid and dumb <br> \n\
running through traffic <br> \n\
is ten times as fun <br> \n\
</body> \n\
</html> \n\
", { false, false, false, false, true,
false, false, false, false, false, false, false,
false, false, false, false,
false, false, false
}
},
//--------- <= Ten characters in
{
" rock&roll",
{ false, false, false, false, false,
true, false, true, true, false, false, true,
false, false, false, false,
false, false, false
}
},
//--------- <= Ten characters in
{
" rock&roll",
{ false, false, false, false, false,
true, true, true, true, false, true, false,
false, false, false, false,
true, false, false
}
},
//--------- <= Ten characters in
{
" roll&rock",
{ false, false, false, false, false,
false, true, true, true, false, true, false,
false, false, false, false,
false, true, false
}
},
//--------- <= Ten characters in
{
" roll&rock",
{ false, false, false, false, false,
true, true, true, true, false, true, true,
false, false, false, false,
false, false, true
}
},
//------------------------------
{
"\xFF\xFF FF FF",
{ false, false, false, false, false,
false, false, false, false, false, false, false,
true, false, false, true,
false, false, false
}
},
//------------------------------
{
"\xFA\xFA FA FA",
{ false, false, false, false, false,
false, false, false, false, false, false, false,
true, false, false, false,
false, false, false
}
},
//------------------------------
{
"\xAF\xAF AF AF",
{ false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, true,
false, false, false
}
},
//------------------------------
{
std::string("\033\000 033 000", 10), // Otherwise, it thinks the NULL is the end of the string
{ false, false, false, false, false,
false, false, false, false, false, false, false,
false, true, false, false,
false, false, false
}
},
//------------------------------
{
std::string("\000\034 000 034", 10), // Otherwise, it thinks the NULL is the end of the string
{ false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, true, false,
false, false, false
}
},
//------------------------------
{
"\033\034 033 034",
{ false, false, false, false, false,
false, false, false, false, false, false, false,
false, true, true, false,
false, false, false
}
},
}; // tests[]
const int32 testCount = sizeof(tests)/sizeof(test_case);
for (int i = 0; i < testCount; i++) {
if (i > 0)
NextSubTestBlock();
test_case &test = tests[i];
// cout << "--------------------------------------------------------------------------------" << endl;
// cout << test.data << endl;
for (int j = 0; j < ruleCount; j++) {
NextSubTest();
// cout << "############################################################" << endl;
// cout << rules[j] << endl;
// cout << test.result[j] << endl;
Rule rule;
BString errorMsg;
status_t err = parse(rules[j], &rule, &errorMsg);
// dumpStr(test.data, "str ");
if (err) {
// cout << "PARSE FAILURE!!!" << endl;
// cout << errorMsg.String() << endl;
}
CHK(err == B_OK);
if (!err) {
BMallocIO data;
data.Write(test.data.data(), test.data.length());//strlen(test.data));
bool match = rule.Sniff(&data);
// cout << match << endl;
// cout << "match == " << (match ? "yes" : "no") << ", "
// << ((match == test.result[j]) ? "SUCCESS" : "FAILURE") << endl;
CHK(match == test.result[j]);
}
}
}
#endif // !TEST_R5
}

View File

@ -14,6 +14,7 @@ public:
//------------------------------------------------------------ //------------------------------------------------------------
void ScannerTest(); void ScannerTest();
void ParserTest(); void ParserTest();
void SnifferTest();
//------------------------------------------------------------ //------------------------------------------------------------
// Helper functions // Helper functions