Skip to content

Commit 91ae096

Browse files
authored
test : Add test to confirm Context expected behavior (#2724)
1 parent fb74565 commit 91ae096

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

opentelemetry-sdk/src/trace/mod.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,53 @@ mod tests {
7676
Context, KeyValue,
7777
};
7878

79+
#[test]
80+
fn span_modification_via_context() {
81+
let exporter = InMemorySpanExporterBuilder::new().build();
82+
let provider = SdkTracerProvider::builder()
83+
.with_span_processor(SimpleSpanProcessor::new(exporter.clone()))
84+
.build();
85+
let tracer = provider.tracer("test_tracer");
86+
87+
#[derive(Debug, PartialEq)]
88+
struct ValueA(u64);
89+
90+
let span = tracer.start("span-name");
91+
92+
// start with Current, which should have no span
93+
let cx = Context::current();
94+
assert!(!cx.has_active_span());
95+
96+
// add span to context
97+
let cx_with_span = cx.with_span(span);
98+
assert!(cx_with_span.has_active_span());
99+
assert!(!cx.has_active_span());
100+
101+
// modify the span by using span_ref from the context
102+
// this is the only way to modify the span as span
103+
// is moved to context.
104+
let span_ref = cx_with_span.span();
105+
span_ref.set_attribute(KeyValue::new("attribute1", "value1"));
106+
107+
// create a new context, which should not affect the original
108+
let cx_with_span_and_more = cx_with_span.with_value(ValueA(1));
109+
110+
// modify the span again using the new context.
111+
// this should still be using the original span itself.
112+
let span_ref_new = cx_with_span_and_more.span();
113+
span_ref_new.set_attribute(KeyValue::new("attribute2", "value2"));
114+
115+
span_ref_new.end();
116+
117+
let exported_spans = exporter
118+
.get_finished_spans()
119+
.expect("Spans are expected to be exported.");
120+
// There should be a single span, with attributes from both modifications.
121+
assert_eq!(exported_spans.len(), 1);
122+
let span = &exported_spans[0];
123+
assert_eq!(span.attributes.len(), 2);
124+
}
125+
79126
#[test]
80127
fn tracer_in_span() {
81128
// Arrange

opentelemetry/src/context.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,43 @@ impl Hasher for IdHasher {
385385
mod tests {
386386
use super::*;
387387

388+
#[test]
389+
fn context_immutable() {
390+
#[derive(Debug, PartialEq)]
391+
struct ValueA(u64);
392+
#[derive(Debug, PartialEq)]
393+
struct ValueB(u64);
394+
395+
// start with Current, which should be an empty context
396+
let cx = Context::current();
397+
assert_eq!(cx.get::<ValueA>(), None);
398+
assert_eq!(cx.get::<ValueB>(), None);
399+
400+
// with_value should return a new context,
401+
// leaving the original context unchanged
402+
let cx_new = cx.with_value(ValueA(1));
403+
404+
// cx should be unchanged
405+
assert_eq!(cx.get::<ValueA>(), None);
406+
assert_eq!(cx.get::<ValueB>(), None);
407+
408+
// cx_new should contain the new value
409+
assert_eq!(cx_new.get::<ValueA>(), Some(&ValueA(1)));
410+
411+
// cx_new should be unchanged
412+
let cx_newer = cx_new.with_value(ValueB(1));
413+
414+
// Cx and cx_new are unchanged
415+
assert_eq!(cx.get::<ValueA>(), None);
416+
assert_eq!(cx.get::<ValueB>(), None);
417+
assert_eq!(cx_new.get::<ValueA>(), Some(&ValueA(1)));
418+
assert_eq!(cx_new.get::<ValueB>(), None);
419+
420+
// cx_newer should contain both values
421+
assert_eq!(cx_newer.get::<ValueA>(), Some(&ValueA(1)));
422+
assert_eq!(cx_newer.get::<ValueB>(), Some(&ValueB(1)));
423+
}
424+
388425
#[test]
389426
fn nested_contexts() {
390427
#[derive(Debug, PartialEq)]

0 commit comments

Comments
 (0)