BiPredicateWithTracing implements BiPredicate<T, U> { @Override public boolean test(T t, U u) { TracingState originalThreadInfo = null; try { originalThreadInfo = linkTracingToCurrentThread(spanStackForExecution, mdcContextMapForExecution); return origBiPredicate.test(t, u); } finally { unlinkTracingFromCurrentThread(originalThreadInfo); } } BiPredicateWithTracing(BiPredicate<T, U> origBiPredicate);  BiPredicateWithTracing(BiPredicate<T, U> origBiPredicate,
                                  Pair<Deque<Span>, Map<String, String>> originalThreadInfo);  BiPredicateWithTracing(BiPredicate<T, U> origBiPredicate,
                                  Deque<Span> spanStackForExecution,
                                  Map<String, String> mdcContextMapForExecution); static BiPredicateWithTracing<T, U> withTracing(BiPredicate<T, U> origBiPredicate); static BiPredicateWithTracing<T, U> withTracing(
        BiPredicate<T, U> origBiPredicate,
        Pair<Deque<Span>, Map<String, String>> originalThreadInfo
    ); static BiPredicateWithTracing<T, U> withTracing(BiPredicate<T, U> origBiPredicate,
                                                                  Deque<Span> spanStackForExecution,
                                                                  Map<String, String> mdcContextMapForExecution); @Override boolean test(T t, U u);  }
@DataProvider(value = { "true | true", "true | false", "false | true", "false | false" }, splitBy = "\\|") @Test public void test_handles_tracing_and_mdc_info_as_expected(boolean throwException, boolean predicateReturnVal) { throwExceptionDuringCall = throwException; returnValIfNoException = predicateReturnVal; Tracer.getInstance().startRequestWithRootSpan("foo"); Deque<Span> spanStack = Tracer.getInstance().getCurrentSpanStackCopy(); Map<String, String> mdcInfo = MDC.getCopyOfContextMap(); BiPredicateWithTracing instance = new BiPredicateWithTracing( biPredicateMock, spanStack, mdcInfo ); resetTracing(); assertThat(Tracer.getInstance().getCurrentSpanStackCopy()).isNull(); assertThat(MDC.getCopyOfContextMap()).isNullOrEmpty(); Throwable ex = null; Boolean result = null; try { result = instance.test(inObj1, inObj2); } catch(Throwable t) { ex = t; } verify(biPredicateMock).test(inObj1, inObj2); if (throwException) { assertThat(ex).isNotNull(); assertThat(result).isNull(); } else { assertThat(ex).isNull(); assertThat(result).isEqualTo(predicateReturnVal); } assertThat(currentSpanStackWhenBiPredicateWasCalled.get(0)).isEqualTo(spanStack); assertThat(currentMdcInfoWhenBiPredicateWasCalled.get(0)).isEqualTo(mdcInfo); assertThat(Tracer.getInstance().getCurrentSpanStackCopy()).isNull(); assertThat(MDC.getCopyOfContextMap()).isNullOrEmpty(); }