Skip to content
This repository was archived by the owner on Jan 26, 2024. It is now read-only.

Commit f3c1f42

Browse files
authored
Make MockTracer's behavior more customizable. (#59)
1 parent 3ef3c24 commit f3c1f42

File tree

6 files changed

+122
-39
lines changed

6 files changed

+122
-39
lines changed

mocktracer/include/opentracing/mocktracer/tracer.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,35 @@ namespace opentracing {
1111
BEGIN_OPENTRACING_ABI_NAMESPACE
1212
namespace mocktracer {
1313

14+
struct PropagationOptions {
15+
// Specifies what key to use when injecting and extracting span context.
16+
std::string propagation_key = "x-ot_span_context";
17+
18+
// If inject_error_code is non-zero, MockTracer::Inject fails with
19+
// inject_error_code.
20+
std::error_code inject_error_code;
21+
22+
// If extract_error_code is non-zero, MockTracer::Extract fails with
23+
// extract_error_code.
24+
std::error_code extract_error_code;
25+
};
26+
1427
struct MockTracerOptions {
28+
// Recorder is sent spans when they are finished. If nullptr, all finished
29+
// spans are dropped.
1530
std::unique_ptr<Recorder> recorder;
31+
32+
// PropagationOptions allows you to customize how the mocktracer's SpanContext
33+
// is propagated.
34+
PropagationOptions propagation_options;
1635
};
1736

1837
// MockTracer provides implements the OpenTracing Tracer API. It provides
1938
// convenient access to finished spans in such a way as to support testing.
2039
class MockTracer : public Tracer,
2140
public std::enable_shared_from_this<MockTracer> {
2241
public:
23-
explicit MockTracer(MockTracerOptions&& options)
24-
: recorder_{std::move(options.recorder)} {}
42+
explicit MockTracer(MockTracerOptions&& options);
2543

2644
std::unique_ptr<Span> StartSpanWithOptions(
2745
string_view operation_name, const StartSpanOptions& options) const
@@ -54,6 +72,7 @@ class MockTracer : public Tracer,
5472

5573
private:
5674
std::unique_ptr<Recorder> recorder_;
75+
PropagationOptions propagation_options_;
5776
std::mutex mutex_;
5877
std::vector<SpanData> spans_;
5978
};

mocktracer/src/mock_span_context.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,17 @@ class MockSpanContext : public SpanContext {
3636
void SetData(SpanContextData& data);
3737

3838
template <class Carrier>
39-
expected<void> Inject(Carrier& writer) const {
39+
expected<void> Inject(const PropagationOptions& propagation_options,
40+
Carrier& writer) const {
4041
std::lock_guard<std::mutex> lock_guard{baggage_mutex_};
41-
return InjectSpanContext(writer, data_);
42+
return InjectSpanContext(propagation_options, writer, data_);
4243
}
4344

4445
template <class Carrier>
45-
expected<bool> Extract(Carrier& reader) {
46+
expected<bool> Extract(const PropagationOptions& propagation_options,
47+
Carrier& reader) {
4648
std::lock_guard<std::mutex> lock_guard{baggage_mutex_};
47-
return ExtractSpanContext(reader, data_);
49+
return ExtractSpanContext(propagation_options, reader, data_);
4850
}
4951

5052
private:

mocktracer/src/propagation.cpp

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
namespace opentracing {
1010
BEGIN_OPENTRACING_ABI_NAMESPACE
1111
namespace mocktracer {
12-
const opentracing::string_view propagation_key = "x-ot-span-context";
13-
1412
static void WriteString(std::ostream& ostream, const std::string& s) {
1513
const uint32_t size = static_cast<uint32_t>(s.size());
1614
ostream.write(reinterpret_cast<const char*>(&size), sizeof(size));
@@ -24,8 +22,9 @@ static void ReadString(std::istream& istream, std::string& s) {
2422
istream.read(&s[0], size);
2523
}
2624

27-
expected<void> InjectSpanContext(std::ostream& carrier,
28-
const SpanContextData& span_context_data) {
25+
expected<void> InjectSpanContext(
26+
const PropagationOptions& /*propagation_options*/, std::ostream& carrier,
27+
const SpanContextData& span_context_data) {
2928
carrier.write(reinterpret_cast<const char*>(&span_context_data.trace_id),
3029
sizeof(&span_context_data.trace_id));
3130
carrier.write(reinterpret_cast<const char*>(&span_context_data.span_id),
@@ -50,8 +49,9 @@ expected<void> InjectSpanContext(std::ostream& carrier,
5049
return {};
5150
}
5251

53-
expected<bool> ExtractSpanContext(std::istream& carrier,
54-
SpanContextData& span_context_data) try {
52+
expected<bool> ExtractSpanContext(
53+
const PropagationOptions& /*propagation_options*/, std::istream& carrier,
54+
SpanContextData& span_context_data) try {
5555
// istream::peek returns EOF if it's in an error state, so check for an error
5656
// state first before checking for an empty stream.
5757
if (!carrier.good()) {
@@ -86,10 +86,12 @@ expected<bool> ExtractSpanContext(std::istream& carrier,
8686
std::make_error_code(std::errc::not_enough_memory));
8787
}
8888

89-
expected<void> InjectSpanContext(const TextMapWriter& carrier,
89+
expected<void> InjectSpanContext(const PropagationOptions& propagation_options,
90+
const TextMapWriter& carrier,
9091
const SpanContextData& span_context_data) {
9192
std::ostringstream ostream;
92-
auto result = InjectSpanContext(ostream, span_context_data);
93+
auto result =
94+
InjectSpanContext(propagation_options, ostream, span_context_data);
9395
if (!result) {
9496
return result;
9597
}
@@ -103,7 +105,7 @@ expected<void> InjectSpanContext(const TextMapWriter& carrier,
103105
std::make_error_code(std::errc::not_enough_memory));
104106
}
105107

106-
result = carrier.Set(propagation_key, context_value);
108+
result = carrier.Set(propagation_options.propagation_key, context_value);
107109
if (!result) {
108110
return result;
109111
}
@@ -142,9 +144,11 @@ static opentracing::expected<opentracing::string_view> LookupKey(
142144

143145
template <class KeyCompare>
144146
static opentracing::expected<bool> ExtractSpanContext(
147+
const PropagationOptions& propagation_options,
145148
const opentracing::TextMapReader& carrier,
146149
SpanContextData& span_context_data, KeyCompare key_compare) {
147-
auto value_maybe = LookupKey(carrier, propagation_key, key_compare);
150+
auto value_maybe =
151+
LookupKey(carrier, propagation_options.propagation_key, key_compare);
148152
if (!value_maybe) {
149153
if (value_maybe.error() == opentracing::key_not_found_error) {
150154
return false;
@@ -165,22 +169,26 @@ static opentracing::expected<bool> ExtractSpanContext(
165169
opentracing::span_context_corrupted_error);
166170
}
167171
std::istringstream istream{base64_decoding};
168-
return ExtractSpanContext(istream, span_context_data);
172+
return ExtractSpanContext(propagation_options, istream, span_context_data);
169173
}
170174

171-
expected<bool> ExtractSpanContext(const TextMapReader& carrier,
175+
expected<bool> ExtractSpanContext(const PropagationOptions& propagation_options,
176+
const TextMapReader& carrier,
172177
SpanContextData& span_context_data) {
173-
return ExtractSpanContext(carrier, span_context_data,
178+
return ExtractSpanContext(propagation_options, carrier, span_context_data,
174179
std::equal_to<string_view>{});
175180
}
176181

177-
expected<void> InjectSpanContext(const HTTPHeadersWriter& carrier,
182+
expected<void> InjectSpanContext(const PropagationOptions& propagation_options,
183+
const HTTPHeadersWriter& carrier,
178184
const SpanContextData& span_context_data) {
179-
return InjectSpanContext(static_cast<const TextMapWriter&>(carrier),
185+
return InjectSpanContext(propagation_options,
186+
static_cast<const TextMapWriter&>(carrier),
180187
span_context_data);
181188
}
182189

183-
expected<bool> ExtractSpanContext(const HTTPHeadersReader& carrier,
190+
expected<bool> ExtractSpanContext(const PropagationOptions& propagation_options,
191+
const HTTPHeadersReader& carrier,
184192
SpanContextData& span_context_data) {
185193
auto iequals = [](opentracing::string_view lhs,
186194
opentracing::string_view rhs) {
@@ -190,7 +198,8 @@ expected<bool> ExtractSpanContext(const HTTPHeadersReader& carrier,
190198
return std::tolower(a) == std::tolower(b);
191199
});
192200
};
193-
return ExtractSpanContext(carrier, span_context_data, iequals);
201+
return ExtractSpanContext(propagation_options, carrier, span_context_data,
202+
iequals);
194203
}
195204
} // namespace mocktracer
196205
END_OPENTRACING_ABI_NAMESPACE

mocktracer/src/propagation.h

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,35 @@
22
#define OPENTRACING_MOCKTRACER_PROPAGATION_H
33

44
#include <opentracing/mocktracer/recorder.h>
5+
#include <opentracing/mocktracer/tracer.h>
56
#include <opentracing/propagation.h>
67

78
namespace opentracing {
89
BEGIN_OPENTRACING_ABI_NAMESPACE
910
namespace mocktracer {
10-
expected<void> InjectSpanContext(std::ostream& carrier,
11+
12+
expected<void> InjectSpanContext(const PropagationOptions& propagation_options,
13+
std::ostream& carrier,
1114
const SpanContextData& span_context_data);
1215

13-
expected<bool> ExtractSpanContext(std::istream& carrier,
16+
expected<bool> ExtractSpanContext(const PropagationOptions& propagation_options,
17+
std::istream& carrier,
1418
SpanContextData& span_context_data);
1519

16-
expected<void> InjectSpanContext(const TextMapWriter& carrier,
20+
expected<void> InjectSpanContext(const PropagationOptions& propagation_options,
21+
const TextMapWriter& carrier,
1722
const SpanContextData& span_context_data);
1823

19-
expected<bool> ExtractSpanContext(const TextMapReader& carrier,
24+
expected<bool> ExtractSpanContext(const PropagationOptions& propagation_options,
25+
const TextMapReader& carrier,
2026
SpanContextData& span_context_data);
2127

22-
expected<void> InjectSpanContext(const HTTPHeadersWriter& carrier,
28+
expected<void> InjectSpanContext(const PropagationOptions& propagation_options,
29+
const HTTPHeadersWriter& carrier,
2330
const SpanContextData& span_context_data);
2431

25-
expected<bool> ExtractSpanContext(const HTTPHeadersReader& carrier,
32+
expected<bool> ExtractSpanContext(const PropagationOptions& propagation_options,
33+
const HTTPHeadersReader& carrier,
2634
SpanContextData& span_context_data);
2735
} // namespace mocktracer
2836
END_OPENTRACING_ABI_NAMESPACE

mocktracer/src/tracer.cpp

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,33 @@
44

55
#include "mock_span.h"
66
#include "mock_span_context.h"
7+
#include "propagation.h"
78

89
namespace opentracing {
910
BEGIN_OPENTRACING_ABI_NAMESPACE
1011
namespace mocktracer {
1112

1213
template <class Carrier>
13-
static expected<void> InjectImpl(const opentracing::SpanContext& span_context,
14+
static expected<void> InjectImpl(const PropagationOptions& propagation_options,
15+
const opentracing::SpanContext& span_context,
1416
Carrier& writer) {
17+
if (propagation_options.inject_error_code.value() != 0) {
18+
return opentracing::make_unexpected(propagation_options.inject_error_code);
19+
}
1520
auto mock_span_context = dynamic_cast<const MockSpanContext*>(&span_context);
1621
if (mock_span_context == nullptr) {
1722
return opentracing::make_unexpected(
1823
opentracing::invalid_span_context_error);
1924
}
20-
return mock_span_context->Inject(writer);
25+
return mock_span_context->Inject(propagation_options, writer);
2126
}
2227

2328
template <class Carrier>
2429
opentracing::expected<std::unique_ptr<opentracing::SpanContext>> ExtractImpl(
25-
Carrier& reader) {
30+
const PropagationOptions& propagation_options, Carrier& reader) {
31+
if (propagation_options.extract_error_code.value() != 0) {
32+
return opentracing::make_unexpected(propagation_options.extract_error_code);
33+
}
2634
MockSpanContext* mock_span_context;
2735
try {
2836
mock_span_context = new MockSpanContext{};
@@ -31,7 +39,7 @@ opentracing::expected<std::unique_ptr<opentracing::SpanContext>> ExtractImpl(
3139
make_error_code(std::errc::not_enough_memory));
3240
}
3341
std::unique_ptr<opentracing::SpanContext> span_context(mock_span_context);
34-
auto result = mock_span_context->Extract(reader);
42+
auto result = mock_span_context->Extract(propagation_options, reader);
3543
if (!result) {
3644
return opentracing::make_unexpected(result.error());
3745
}
@@ -41,6 +49,10 @@ opentracing::expected<std::unique_ptr<opentracing::SpanContext>> ExtractImpl(
4149
return std::move(span_context);
4250
}
4351

52+
MockTracer::MockTracer(MockTracerOptions&& options)
53+
: recorder_{std::move(options.recorder)},
54+
propagation_options_{std::move(options.propagation_options)} {}
55+
4456
std::unique_ptr<Span> MockTracer::StartSpanWithOptions(
4557
string_view operation_name, const StartSpanOptions& options) const
4658
noexcept try {
@@ -59,32 +71,32 @@ void MockTracer::Close() noexcept {
5971

6072
expected<void> MockTracer::Inject(const SpanContext& sc,
6173
std::ostream& writer) const {
62-
return InjectImpl(sc, writer);
74+
return InjectImpl(propagation_options_, sc, writer);
6375
}
6476

6577
expected<void> MockTracer::Inject(const SpanContext& sc,
6678
const TextMapWriter& writer) const {
67-
return InjectImpl(sc, writer);
79+
return InjectImpl(propagation_options_, sc, writer);
6880
}
6981

7082
expected<void> MockTracer::Inject(const SpanContext& sc,
7183
const HTTPHeadersWriter& writer) const {
72-
return InjectImpl(sc, writer);
84+
return InjectImpl(propagation_options_, sc, writer);
7385
}
7486

7587
expected<std::unique_ptr<SpanContext>> MockTracer::Extract(
7688
std::istream& reader) const {
77-
return ExtractImpl(reader);
89+
return ExtractImpl(propagation_options_, reader);
7890
}
7991

8092
expected<std::unique_ptr<SpanContext>> MockTracer::Extract(
8193
const TextMapReader& reader) const {
82-
return ExtractImpl(reader);
94+
return ExtractImpl(propagation_options_, reader);
8395
}
8496

8597
expected<std::unique_ptr<SpanContext>> MockTracer::Extract(
8698
const HTTPHeadersReader& reader) const {
87-
return ExtractImpl(reader);
99+
return ExtractImpl(propagation_options_, reader);
88100
}
89101
} // namespace mocktracer
90102
END_OPENTRACING_ABI_NAMESPACE

mocktracer/test/propagation_test.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,10 @@ struct HTTPHeadersCarrier : HTTPHeadersReader, HTTPHeadersWriter {
7070
};
7171

7272
TEST_CASE("propagation") {
73+
const char* propagation_key = "propagation-key";
7374
auto recorder = new InMemoryRecorder{};
7475
MockTracerOptions tracer_options;
76+
tracer_options.propagation_options.propagation_key = propagation_key;
7577
tracer_options.recorder.reset(recorder);
7678
auto tracer = std::shared_ptr<opentracing::Tracer>{
7779
new MockTracer{std::move(tracer_options)}};
@@ -82,6 +84,11 @@ TEST_CASE("propagation") {
8284
CHECK(span);
8385
span->SetBaggageItem("abc", "123");
8486

87+
SECTION("Propagation uses the specified propagation_key.") {
88+
CHECK(tracer->Inject(span->context(), text_map_carrier));
89+
CHECK(text_map.count(propagation_key) == 1);
90+
}
91+
8592
SECTION("Inject, extract, inject yields the same text_map.") {
8693
CHECK(tracer->Inject(span->context(), text_map_carrier));
8794
auto injection_map1 = text_map;
@@ -200,4 +207,30 @@ TEST_CASE("propagation") {
200207
CHECK(std::all_of(value.begin(), value.end(), is_base64_char));
201208
CHECK(value.size() % 4 == 0);
202209
}
210+
211+
SECTION("Inject fails if inject_error_code is non-zero.") {
212+
MockTracerOptions tracer_options_fail;
213+
auto error_code = std::make_error_code(std::errc::network_down);
214+
tracer_options_fail.propagation_options.inject_error_code = error_code;
215+
tracer = std::shared_ptr<opentracing::Tracer>{
216+
new MockTracer{std::move(tracer_options_fail)}};
217+
218+
std::ostringstream oss;
219+
auto rcode = tracer->Inject(span->context(), oss);
220+
CHECK(!rcode);
221+
CHECK(rcode.error() == error_code);
222+
}
223+
224+
SECTION("Extract fails if extract_error_code is non-zero.") {
225+
MockTracerOptions tracer_options_fail;
226+
auto error_code = std::make_error_code(std::errc::network_down);
227+
tracer_options_fail.propagation_options.extract_error_code = error_code;
228+
tracer = std::shared_ptr<opentracing::Tracer>{
229+
new MockTracer{std::move(tracer_options_fail)}};
230+
231+
CHECK(tracer->Inject(span->context(), text_map_carrier));
232+
auto span_context_maybe = tracer->Extract(text_map_carrier);
233+
CHECK(!span_context_maybe);
234+
CHECK(span_context_maybe.error() == error_code);
235+
}
203236
}

0 commit comments

Comments
 (0)