Skip to content

Commit ec167c5

Browse files
committed
add another test for out-of-order async drops
1 parent 013bc4b commit ec167c5

File tree

1 file changed

+35
-5
lines changed

1 file changed

+35
-5
lines changed

opentelemetry/src/context.rs

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ mod tests {
670670
for _ in 0..16 {
671671
let cx_guard = Context::current().with_value(ValueA(1)).attach();
672672
assert_eq!(cx_guard.cx_pos, ContextStack::MAX_POS);
673-
assert_eq!(Context::current().get(), Some(&ValueA(2)));
673+
assert_eq!(Context::current().get::<ValueA>(), Some(&ValueA(2)));
674674
assert_eq!(Context::current().get(), Some(&ValueB(stack_max_pos - 2)));
675675
guards.push(cx_guard);
676676
}
@@ -783,7 +783,6 @@ mod tests {
783783
/// 2. Values added during async operations do not affect parent context
784784
#[tokio::test]
785785
async fn test_async_context_propagation() {
786-
787786
// A nested async operation we'll use to test propagation
788787
async fn nested_operation() {
789788
// Verify we can see the parent context's value
@@ -795,7 +794,7 @@ mod tests {
795794

796795
// Create new context
797796
let cx_with_both = Context::current()
798-
.with_value(ValueA(43))// override ValueA
797+
.with_value(ValueA(43)) // override ValueA
799798
.with_value(ValueB(24)); // Add new ValueB
800799

801800
// Run nested async operation with both values
@@ -827,8 +826,8 @@ mod tests {
827826
"New value should persist across await points"
828827
);
829828
}
830-
.with_context(cx_with_both)
831-
.await;
829+
.with_context(cx_with_both)
830+
.await;
832831
}
833832

834833
// Set up initial context with ValueA
@@ -862,4 +861,35 @@ mod tests {
862861
"Current context should not have async operation's values"
863862
);
864863
}
864+
865+
#[tokio::test]
866+
async fn test_out_of_order_context_detachment_futures() {
867+
// This function returns a future, but doesn't await it
868+
// It will complete before the future that it creates.
869+
async fn create_a_future() -> impl std::future::Future<Output = ()> {
870+
// Create a future that will do some work, referencing our current
871+
// context, but don't await it.
872+
async {
873+
let _guard = Context::new().with_value(ValueB(2)).attach();
874+
// Longer work
875+
sleep(Duration::from_millis(50)).await;
876+
}
877+
.with_context(Context::current())
878+
}
879+
880+
// Create our base context
881+
let parent_cx = Context::new().with_value(ValueA(42));
882+
883+
// await our nested function, which will create and detach a context
884+
let future = create_a_future().with_context(parent_cx).await;
885+
886+
// Execute the future. The completion of the future will result in an out-of-order drop,
887+
// as the parent context created by create_a_future was already dropped earlier.
888+
future.await;
889+
890+
// Nothing terrible (e.g., panics!) should happen, and we should definitely not have any
891+
// values attached to our current context that were set in the nested operations.
892+
assert_eq!(Context::current().get::<ValueA>(), None);
893+
assert_eq!(Context::current().get::<ValueB>(), None);
894+
}
865895
}

0 commit comments

Comments
 (0)