We now have a new feature, called the Piglet test harness, that fills the gap in test scope.
The Piglet test harness allows you to use Lua scripts to exercise individual methods. Let's say you are developing a new Snort++ inspector called FooInspector. For simplicity's sake, all FooInspector will do is unset the PKT_FROM_CLIENT flag on a packet if it is set:
// foo_inspector.cc
// ... Plugin boilerplate omitted
class FooFlowData;
class FooInspector : public Inspector
{
public:
FooInspector() { }
void eval(Packet*) override;
}
void FooInspector::eval(Packet* p)
{
if ( !p->from_client() )
return;
p->packet_flags &= ~PKT_FROM_CLIENT;
}
// ... Plugin boilerplate omitted
Now we create a test harness script to setup a Packet, call FooInspector.eval() on it, and then inspect the packet flags:
-- foo.lua
-- Required plugin header
plugin =
{
type = "piglet",
version = 1,
name = ""
}
PKT_FROM_CLIENT = 0x80
-- Piglet test harness header
piglet =
{
name = "make sure that FooInspector foos",
-- Plugin type
type = "inspector",
-- Plugin name
target = "foo_inspector",
-- Test entry point
test = function()
local buf = RawBuffer.new(1024)
local p = Packet.new(buf, 0, 100)
p:set_fields({
packet_flags = PKT_FROM_CLIENT
})
-- Call FooInspector.eval()
Inspector.eval(p)
if p:get_fields().packet_flags == 0 then
-- test passed
return true
end
-- test failed
return false
end
}
To run Snort in Piglet mode, we must first compile with piglet mode enabled. In CMake, do this by running cmake with -DENABLE_PIGLET:BOOL=ON. If you are using autotools, pass the --enable-piglet flag to configure. Then, simply run snort with --script-path set to the directory containing the test script and the --piglet flag.
snort --piglet --script-path=/path/to/foo/tests