package brave.internal;
import brave.Tracer;
import brave.Tracing;
import brave.propagation.CurrentTraceContext;
import brave.propagation.TraceContext;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class StrictCurrentTraceContextTest {
ExecutorService executor = Executors.newSingleThreadExecutor();
// override default so that it isn't inheritable
CurrentTraceContext currentTraceContext = new StrictCurrentTraceContext();
Tracer tracer = Tracing.newBuilder().build().tracer();
TraceContext context = tracer.newTrace().context();
TraceContext context2 = tracer.newTrace().context();
@After public void after() throws InterruptedException {
executor.shutdownNow();
executor.awaitTermination(1, TimeUnit.SECONDS);
}
/**
* When using strict current context, scope is per thread,instance. Interactions like JDBC will
* need to share a static instance explicitly.
*/
@Test public void instancesAreIndependent() {
CurrentTraceContext.Default currentTraceContext2 = new CurrentTraceContext.Default();
try (CurrentTraceContext.Scope scope1 = currentTraceContext.newScope(context)) {
assertThat(currentTraceContext2.get()).isNull();
try (CurrentTraceContext.Scope scope2 = currentTraceContext2.newScope(context2)) {
assertThat(currentTraceContext.get()).isEqualTo(context);
assertThat(currentTraceContext2.get()).isEqualTo(context2);
}
}
}
@Test public void scope_isNotInheritable() throws InterruptedException {
final TraceContext[] threadValue = new TraceContext[1];
try (CurrentTraceContext.Scope scope = currentTraceContext.newScope(context)) {
Thread t = new Thread(() -> { // should not inherit scope!
threadValue[0] = currentTraceContext.get();
});
t.start();
t.join();
assertThat(threadValue[0]).isNull();
}
}
@Test public void scope_canClearScope() {
try (CurrentTraceContext.Scope scope = currentTraceContext.newScope(context)) {
try (CurrentTraceContext.Scope noScope = currentTraceContext.newScope(null)) {
assertThat(currentTraceContext.get())
.isNull();
}
// old context reverted
assertThat(currentTraceContext.get())
.isEqualTo(context);
}
}
@Test public void scope_enforcesCloseOnSameThread() throws InterruptedException {
final Exception[] spawnedThreadException = new Exception[1];
Thread scopingThread = new Thread(() -> {
try (CurrentTraceContext.Scope scope = currentTraceContext.newScope(context)) {
Thread spawnedThread = new Thread(() -> { // should not inherit scope!
try {
scope.close();
} catch (IllegalStateException e) {
spawnedThreadException[0] = e;
}
}, "spawned thread");
spawnedThread.start();
spawnedThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}, "scoping thread");
scopingThread.start();
scopingThread.join();
assertThat(spawnedThreadException[0])
.hasMessage("scope closed in a different thread: spawned thread");
assertThat(spawnedThreadException[0].getCause())
.hasMessage("Thread scoping thread opened scope for " + context + " here:");
}
}