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
|
#include <opentracing/mocktracer/in_memory_recorder.h>
#include <opentracing/mocktracer/json.h>
#include <opentracing/mocktracer/json_recorder.h>
#include <opentracing/mocktracer/tracer.h>
#include <opentracing/noop.h>
#include <sstream>
#define CATCH_CONFIG_MAIN
#include <opentracing/catch2/catch.hpp>
using namespace opentracing;
using namespace mocktracer;
TEST_CASE("tracer") {
auto recorder = new InMemoryRecorder{};
MockTracerOptions tracer_options;
tracer_options.recorder.reset(recorder);
auto tracer = std::shared_ptr<opentracing::Tracer>{
new MockTracer{std::move(tracer_options)}};
SECTION("MockTracer can be constructed without a recorder.") {
auto norecorder_tracer = std::shared_ptr<opentracing::Tracer>{
new MockTracer{MockTracerOptions{}}};
auto span = norecorder_tracer->StartSpan("a");
}
SECTION("StartSpan applies the provided tags.") {
{
auto span =
tracer->StartSpan("a", {SetTag("abc", 123), SetTag("xyz", true)});
CHECK(span);
span->Finish();
}
auto span = recorder->top();
CHECK(span.operation_name == "a");
std::map<std::string, Value> expected_tags = {{"abc", 123}, {"xyz", true}};
CHECK(span.tags == expected_tags);
}
SECTION("You can set a single child-of reference when starting a span.") {
auto span_a = tracer->StartSpan("a");
CHECK(span_a);
span_a->Finish();
auto span_b = tracer->StartSpan("b", {ChildOf(&span_a->context())});
CHECK(span_b);
span_b->Finish();
auto spans = recorder->spans();
CHECK(spans.at(0).span_context.trace_id ==
spans.at(1).span_context.trace_id);
std::vector<SpanReferenceData> expected_references = {
{SpanReferenceType::ChildOfRef, spans.at(0).span_context.trace_id,
spans.at(0).span_context.span_id}};
CHECK(spans.at(1).references == expected_references);
}
SECTION("You can set a single follows-from reference when starting a span.") {
auto span_a = tracer->StartSpan("a");
CHECK(span_a);
span_a->Finish();
auto span_b = tracer->StartSpan("b", {FollowsFrom(&span_a->context())});
CHECK(span_b);
span_b->Finish();
auto spans = recorder->spans();
CHECK(spans.at(0).span_context.trace_id ==
spans.at(1).span_context.trace_id);
std::vector<SpanReferenceData> expected_references = {
{SpanReferenceType::FollowsFromRef, spans.at(0).span_context.trace_id,
spans.at(0).span_context.span_id}};
CHECK(spans.at(1).references == expected_references);
}
SECTION("Multiple references are supported when starting a span.") {
auto span_a = tracer->StartSpan("a");
CHECK(span_a);
auto span_b = tracer->StartSpan("b");
CHECK(span_b);
auto span_c = tracer->StartSpan(
"c", {ChildOf(&span_a->context()), FollowsFrom(&span_b->context())});
span_a->Finish();
span_b->Finish();
span_c->Finish();
auto spans = recorder->spans();
std::vector<SpanReferenceData> expected_references = {
{SpanReferenceType::ChildOfRef, spans.at(0).span_context.trace_id,
spans.at(0).span_context.span_id},
{SpanReferenceType::FollowsFromRef, spans.at(1).span_context.trace_id,
spans.at(1).span_context.span_id}};
CHECK(spans.at(2).references == expected_references);
}
SECTION(
"Baggage from the span references are copied over to a new span "
"context") {
auto span_a = tracer->StartSpan("a");
CHECK(span_a);
span_a->SetBaggageItem("a", "1");
auto span_b = tracer->StartSpan("b");
CHECK(span_b);
span_b->SetBaggageItem("b", "2");
auto span_c = tracer->StartSpan(
"c", {ChildOf(&span_a->context()), ChildOf(&span_b->context())});
CHECK(span_c);
CHECK(span_c->BaggageItem("a") == "1");
CHECK(span_c->BaggageItem("b") == "2");
}
SECTION("References to non-MockTracer spans and null pointers are ignored.") {
auto noop_tracer = MakeNoopTracer();
auto noop_span = noop_tracer->StartSpan("noop");
CHECK(noop_span);
StartSpanOptions options;
options.references.push_back(
std::make_pair(SpanReferenceType::ChildOfRef, &noop_span->context()));
options.references.push_back(
std::make_pair(SpanReferenceType::ChildOfRef, nullptr));
auto span = tracer->StartSpanWithOptions("a", options);
CHECK(span);
span->Finish();
CHECK(recorder->top().references.size() == 0);
}
SECTION("Calling Finish a second time does nothing.") {
auto span = tracer->StartSpan("a");
CHECK(span);
span->Finish();
CHECK(recorder->size() == 1);
span->Finish();
CHECK(recorder->size() == 1);
}
SECTION("FinishWithOptions applies provided log records.") {
std::vector<LogRecord> logs;
{
auto span = tracer->StartSpan("a");
CHECK(span);
FinishSpanOptions options;
auto timestamp = SystemClock::now();
logs = {{timestamp, {{"abc", 123}}}};
options.log_records = logs;
span->FinishWithOptions(options);
}
auto span = recorder->top();
CHECK(span.operation_name == "a");
CHECK(span.logs == logs);
}
SECTION("Logs can be added to an active span.") {
{
auto span = tracer->StartSpan("a");
CHECK(span);
span->Log({{"abc", 123}});
}
auto span = recorder->top();
std::vector<std::pair<std::string, Value>> fields = {{"abc", 123}};
CHECK(span.logs.at(0).fields == fields);
}
SECTION("The operation name can be changed after the span is started.") {
auto span = tracer->StartSpan("a");
CHECK(span);
span->SetOperationName("b");
span->Finish();
CHECK(recorder->top().operation_name == "b");
}
SECTION("Tags can be specified after a span is started.") {
auto span = tracer->StartSpan("a");
CHECK(span);
span->SetTag("abc", 123);
span->Finish();
std::map<std::string, Value> expected_tags = {{"abc", 123}};
CHECK(recorder->top().tags == expected_tags);
}
}
TEST_CASE("json_recorder") {
auto oss = new std::ostringstream{};
MockTracerOptions tracer_options;
tracer_options.recorder = std::unique_ptr<Recorder>{
new JsonRecorder{std::unique_ptr<std::ostream>{oss}}};
auto tracer =
std::shared_ptr<Tracer>{new MockTracer{std::move(tracer_options)}};
SECTION("Spans are serialized to the stream upon Close.") {
auto span = tracer->StartSpan("a");
CHECK(span);
span->Finish();
tracer->Close();
CHECK(!oss->str().empty());
}
}
|