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
|
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#define CAF_SUITE tracing_data
#include "caf/tracing_data.hpp"
#include "core-test.hpp"
#include <vector>
#include "caf/actor_profiler.hpp"
#include "caf/binary_deserializer.hpp"
#include "caf/binary_serializer.hpp"
#include "caf/config.hpp"
#include "caf/tracing_data_factory.hpp"
#ifdef CAF_ENABLE_ACTOR_PROFILER
using std::string;
using namespace caf;
namespace {
class dummy_tracing_data : public tracing_data {
public:
string value;
dummy_tracing_data(string value) : value(std::move(value)) {
// nop
}
bool serialize(serializer& sink) const override {
return sink.apply(value);
}
bool serialize(binary_serializer& sink) const override {
return sink.apply(value);
}
};
class dummy_tracing_data_factory : public tracing_data_factory {
public:
bool deserialize(deserializer& source,
std::unique_ptr<tracing_data>& dst) const override {
return deserialize_impl(source, dst);
}
bool deserialize(binary_deserializer& source,
std::unique_ptr<tracing_data>& dst) const override {
return deserialize_impl(source, dst);
}
private:
template <class Deserializer>
bool deserialize_impl(Deserializer& source,
std::unique_ptr<tracing_data>& dst) const {
string value;
if (!source.apply(value))
return false;
dst.reset(new dummy_tracing_data(std::move(value)));
return true;
}
};
class dummy_profiler : public actor_profiler {
public:
void add_actor(const local_actor&, const local_actor*) override {
// nop
}
void remove_actor(const local_actor&) override {
// nop
}
void before_processing(const local_actor&, const mailbox_element&) override {
// nop
}
void after_processing(const local_actor&, invoke_message_result) override {
// nop
}
void before_sending(const local_actor& self,
mailbox_element& element) override {
element.tracing_id.reset(new dummy_tracing_data(self.name()));
}
void before_sending_scheduled(const local_actor& self,
actor_clock::time_point,
mailbox_element& element) override {
element.tracing_id.reset(new dummy_tracing_data(self.name()));
}
};
actor_system_config& init(actor_system_config& cfg, actor_profiler& profiler,
tracing_data_factory& factory) {
test_coordinator_fixture<>::init_config(cfg);
cfg.profiler = &profiler;
cfg.tracing_context = &factory;
return cfg;
}
struct fixture {
using scheduler_type = caf::scheduler::test_coordinator;
fixture()
: sys(init(cfg, profiler, factory)),
sched(dynamic_cast<scheduler_type&>(sys.scheduler())) {
run();
}
void run() {
sched.run();
}
dummy_profiler profiler;
dummy_tracing_data_factory factory;
actor_system_config cfg;
actor_system sys;
scheduler_type& sched;
};
const std::string& tracing_id(local_actor* self) {
auto element = self->current_mailbox_element();
if (element == nullptr)
CAF_FAIL("current_mailbox_element == null");
auto tid = element->tracing_id.get();
if (tid == nullptr)
CAF_FAIL("tracing_id == null");
auto dummy_tid = dynamic_cast<dummy_tracing_data*>(tid);
if (dummy_tid == nullptr)
CAF_FAIL("dummy_tracing_id == null");
return dummy_tid->value;
}
# define NAMED_ACTOR_STATE(type) \
struct type##_state { \
static inline const char* name = #type; \
}
NAMED_ACTOR_STATE(alice);
NAMED_ACTOR_STATE(bob);
NAMED_ACTOR_STATE(carl);
} // namespace
BEGIN_FIXTURE_SCOPE(fixture)
CAF_TEST(profilers inject tracing data into asynchronous messages) {
MESSAGE("spawn a foo and a bar");
auto carl_fun = [](stateful_actor<carl_state>* self) -> behavior {
return {
[=](const string& str) {
CHECK_EQ(str, "hello carl");
CHECK_EQ(tracing_id(self), "bob");
},
};
};
auto bob_fun = [](stateful_actor<bob_state>* self, actor carl) -> behavior {
return {
[=](const string& str) {
CHECK_EQ(str, "hello bob");
CHECK_EQ(tracing_id(self), "alice");
self->send(carl, "hello carl");
},
};
};
auto alice_fun = [](stateful_actor<alice_state>* self, actor bob) {
self->send(bob, "hello bob");
};
sys.spawn(alice_fun, sys.spawn(bob_fun, sys.spawn(carl_fun)));
run();
}
CAF_TEST(tracing data is serializable) {
byte_buffer buf;
binary_serializer sink{sys, buf};
tracing_data_ptr data{new dummy_tracing_data("iTrace")};
CHECK(sink.apply(data));
binary_deserializer source{sys, buf};
tracing_data_ptr copy;
CHECK(source.apply(copy));
CAF_REQUIRE_NOT_EQUAL(copy.get(), nullptr);
CHECK_EQ(dynamic_cast<dummy_tracing_data&>(*copy).value, "iTrace");
}
END_FIXTURE_SCOPE()
#endif // CAF_ENABLE_ACTOR_PROFILER
|