@@ -0,0 +1,119 @@
#include "broker/bro.hh"
#include "broker/data.hh"

namespace broker {
namespace bro {

static const count ProtocolVersion = 1;

Message::Message(Type type) : type_(type) {
}

Message::Message(data x) {
auto v = get<vector>(x);

if (v.size() != 2)
throw std::runtime_error("broken Bro message header");

auto hdr = get<vector>(v[0]);
content_ = get<vector>(v[1]);

if (hdr.size() != 2)
throw std::runtime_error("broken Bro message header");

version_ = get<count>(hdr[0]);

if (version_ != ProtocolVersion)
throw std::runtime_error("unsupported Bro message version");

switch (get<count>(hdr[1])) {
case Type::Event:
type_ = Type::Event;
break;
case Type::LogCreate:
type_ = Type::LogCreate;
break;
case Type::LogWrite:
type_ = Type::LogWrite;
break;
default:
throw std::runtime_error("unsupported Bro message type");
};
}

template <>
void EventBase::init() {
if (type_ != Type::Event)
throw std::runtime_error("not a Bro event");

if (content_.size() != 2)
throw std::runtime_error("broken Bro event");

try {
args_.name = get<std::string>(content_[0]);
args_.args = get<vector>(content_[1]);
} catch (const bad_variant_access& e) {
throw std::runtime_error("unexpected Bro event arguments");
}
}

template <>
data EventBase::as_data() const {
auto hdr = vector{ProtocolVersion, static_cast<count>(Type::Event)};
auto content = vector{args_.name, vector{args_.args}};
return vector{std::move(hdr), std::move(content)};
}

template <>
void LogCreate::init() {
if (type_ != Type::LogCreate)
throw std::runtime_error("not a Bro LogCreate");

if (content_.size() != 4)
throw std::runtime_error("broken Bro LogCreate");

try {
args_.stream_id = get<enum_value>(content_[0]);
args_.writer_id = get<enum_value>(content_[1]);
args_.writer_info = content_[2];
args_.fields_data = content_[3];
} catch (const bad_variant_access& e) {
throw std::runtime_error("unexpected Bro LogCreate arguments");
}
}

template <>
data LogCreate::as_data() const {
auto hdr = vector{ProtocolVersion, static_cast<count>(Type::LogCreate)};
auto args = vector{args_.stream_id, args_.writer_id, args_.writer_info,
args_.fields_data};
return vector{std::move(hdr), std::move(args)};
}

template <>
void LogWrite::init() {
if (type_ != Type::LogWrite)
throw std::runtime_error("not a Bro LogWrite");

if (content_.size() != 4)
throw std::runtime_error("broken Bro LogWrite");

try {
args_.stream_id = get<enum_value>(content_[0]);
args_.writer_id = get<enum_value>(content_[1]);
args_.path = content_[2];
args_.vals_data = content_[3];
} catch (const bad_variant_access& e) {
throw std::runtime_error("unexpected Bro LogWrite arguments");
}
}

template <>
data LogWrite::as_data() const {
auto hdr = vector{ProtocolVersion, static_cast<count>(Type::LogWrite)};
auto args
= vector{args_.stream_id, args_.writer_id, args_.path, args_.vals_data};
return vector{std::move(hdr), std::move(args)};
}
}
}
@@ -8,6 +8,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR})

set(tests
cpp/backend.cc
cpp/bro.cc
cpp/core.cc
cpp/data.cc
cpp/event_subscriber.cc
@@ -58,6 +59,9 @@ endforeach ()
# -- Python -------------------------------------------------------------------

if (BROKER_PYTHON_BINDINGS)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/python/run-bro.in
${CMAKE_CURRENT_BINARY_DIR}/python/run-bro)

macro(make_python_test name)
set(script ${CMAKE_CURRENT_SOURCE_DIR}/python/${name}.py)
set(test_name python-${name})
@@ -69,8 +73,9 @@ if (BROKER_PYTHON_BINDINGS)
"PYTHONPATH=${BROKER_PYTHON_STAGING_DIR}")
endmacro()

make_python_test(topic)
make_python_test(data)
make_python_test(bro)
make_python_test(communication)
make_python_test(data)
make_python_test(store)
make_python_test(topic)
endif ()
@@ -0,0 +1,23 @@
//
// We leave testing the actual communication with Bro to Python tests. Here
// we just check that the messages are constructed and parsed correctly.
//

#include "broker/broker.hh"
#include "broker/bro.hh"

#define SUITE bro
#include "test.hpp"

using namespace broker;

TEST(event) {
auto args = vector{1, "s", port(42, port::protocol::tcp)};
bro::Event ev("test", args);
data d = ev;
auto hdr = vector{broker::count(1), broker::count(1)};
CHECK_EQUAL(d, (vector{hdr, vector{"test", args}}));
bro::Event ev2(d);
CHECK_EQUAL(ev2.name(), "test");
CHECK_EQUAL(ev2.args(), args);
}
@@ -10,6 +10,15 @@
import broker
import broker.bro

def run_bro_path():
base = os.path.realpath(__file__)
for d in (os.path.join(os.path.join(os.path.dirname(base), "../../build")), os.getcwd()):
run_bro = os.path.abspath(os.path.join(d, "tests/python/run-bro"))
if os.path.exists(run_bro):
return run_bro

return "bro" # # Hope for the best ...

BroPing = """
redef Broker::default_connect_retry=1secs;
redef Broker::default_listen_retry=1secs;
@@ -54,8 +63,7 @@ def RunBro(script, port):
tmp = tempfile.NamedTemporaryFile(mode="w", suffix=".bro", delete=False)
print(script.replace("__PORT__", str(port)), file=tmp)
tmp.close()
os.environ["BROPATH"] = "/home/robin/bro/bro-matthias/scripts:/home/robin/bro/bro-matthias/scripts/policy:/home/robin/bro/bro-matthias/scripts/site:/home/robin/bro/bro-matthias/build/scripts"
subprocess.check_call(["/home/robin/bro/bro-matthias/build/src/bro", "-b", "-B", "broker", tmp.name])
subprocess.check_call([run_bro_path(), "-b", "-B", "broker", tmp.name])
return True
except subprocess.CalledProcessError:
return False
@@ -75,13 +83,13 @@ def test_ping(self):
for i in range(0, 6):
(t, msg) = sub.get()
ev = broker.bro.Event(msg)
(s, c) = ev.args
(s, c) = ev.args()

self.assertEqual(ev.name, "ping")
self.assertEqual(ev.name(), "ping")
self.assertEqual(s, "x" + "Xx" * i)
self.assertEqual(c, i)

ev = broker.bro.Event("pong", s + "X", c)
ev = broker.bro.Event("pong", (s + "X", c))
ep.publish("/test", ev)

ep.shutdown()
@@ -0,0 +1,13 @@
#! /usr/bin/env bash

if [ -n "${BRO_EXECUTABLE}" ]; then
exec "${BRO_EXECUTABLE}" $@

elif [ -n "${BRO_PATH_DEV}" ]; then
source "${BRO_PATH_DEV}"
exec bro $@

else
echo "No Bro executable available" >&2
exit 1
fi