1 /* 2 * Copyright 2017, OpenCensus Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package io.opencensus.trace; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static org.mockito.Matchers.same; 21 import static org.mockito.Mockito.verify; 22 import static org.mockito.Mockito.verifyZeroInteractions; 23 24 import io.grpc.Context; 25 import io.opencensus.common.Scope; 26 import io.opencensus.trace.unsafe.ContextUtils; 27 import java.util.concurrent.Callable; 28 import org.junit.Before; 29 import org.junit.Test; 30 import org.junit.runner.RunWith; 31 import org.junit.runners.JUnit4; 32 import org.mockito.Mock; 33 import org.mockito.MockitoAnnotations; 34 35 /** Unit tests for {@link CurrentSpanUtils}. */ 36 @RunWith(JUnit4.class) 37 public class CurrentSpanUtilsTest { 38 @Mock private Span span; 39 40 @Before setUp()41 public void setUp() { 42 MockitoAnnotations.initMocks(this); 43 } 44 45 // TODO(bdrutu): When update to junit 4.13 use assertThrows instead of this. executeRunnableAndExpectError(Runnable runnable, Throwable error)46 private void executeRunnableAndExpectError(Runnable runnable, Throwable error) { 47 boolean called = false; 48 try { 49 CurrentSpanUtils.withSpan(span, true, runnable).run(); 50 } catch (Throwable e) { 51 assertThat(e).isEqualTo(error); 52 called = true; 53 } 54 assertThat(called).isTrue(); 55 } 56 57 // TODO(bdrutu): When update to junit 4.13 use assertThrows instead of this. executeCallableAndExpectError(Callable<Object> callable, Throwable error)58 private void executeCallableAndExpectError(Callable<Object> callable, Throwable error) { 59 boolean called = false; 60 try { 61 CurrentSpanUtils.withSpan(span, true, callable).call(); 62 } catch (Throwable e) { 63 assertThat(e).isEqualTo(error); 64 called = true; 65 } 66 assertThat(called).isTrue(); 67 } 68 69 @Test getCurrentSpan_WhenNoContext()70 public void getCurrentSpan_WhenNoContext() { 71 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 72 } 73 74 @Test getCurrentSpan()75 public void getCurrentSpan() { 76 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 77 Context origContext = Context.current().withValue(ContextUtils.CONTEXT_SPAN_KEY, span).attach(); 78 // Make sure context is detached even if test fails. 79 try { 80 assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); 81 } finally { 82 Context.current().detach(origContext); 83 } 84 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 85 } 86 87 @Test withSpan_CloseDetaches()88 public void withSpan_CloseDetaches() { 89 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 90 Scope ws = CurrentSpanUtils.withSpan(span, false); 91 try { 92 assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); 93 } finally { 94 ws.close(); 95 } 96 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 97 verifyZeroInteractions(span); 98 } 99 100 @Test withSpan_CloseDetachesAndEndsSpan()101 public void withSpan_CloseDetachesAndEndsSpan() { 102 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 103 Scope ss = CurrentSpanUtils.withSpan(span, true); 104 try { 105 assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); 106 } finally { 107 ss.close(); 108 } 109 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 110 verify(span).end(same(EndSpanOptions.DEFAULT)); 111 } 112 113 @Test withSpanRunnable()114 public void withSpanRunnable() { 115 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 116 Runnable runnable = 117 new Runnable() { 118 @Override 119 public void run() { 120 // When we run the runnable we will have the span in the current Context. 121 assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); 122 } 123 }; 124 CurrentSpanUtils.withSpan(span, false, runnable).run(); 125 verifyZeroInteractions(span); 126 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 127 } 128 129 @Test withSpanRunnable_EndSpan()130 public void withSpanRunnable_EndSpan() { 131 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 132 Runnable runnable = 133 new Runnable() { 134 @Override 135 public void run() { 136 // When we run the runnable we will have the span in the current Context. 137 assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); 138 } 139 }; 140 CurrentSpanUtils.withSpan(span, true, runnable).run(); 141 verify(span).end(EndSpanOptions.DEFAULT); 142 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 143 } 144 145 @Test withSpanRunnable_WithError()146 public void withSpanRunnable_WithError() { 147 final AssertionError error = new AssertionError("MyError"); 148 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 149 Runnable runnable = 150 new Runnable() { 151 @Override 152 public void run() { 153 // When we run the runnable we will have the span in the current Context. 154 assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); 155 throw error; 156 } 157 }; 158 executeRunnableAndExpectError(runnable, error); 159 verify(span).setStatus(Status.UNKNOWN.withDescription("MyError")); 160 verify(span).end(EndSpanOptions.DEFAULT); 161 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 162 } 163 164 @Test withSpanRunnable_WithErrorNoMessage()165 public void withSpanRunnable_WithErrorNoMessage() { 166 final AssertionError error = new AssertionError(); 167 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 168 Runnable runnable = 169 new Runnable() { 170 @Override 171 public void run() { 172 // When we run the runnable we will have the span in the current Context. 173 assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); 174 throw error; 175 } 176 }; 177 executeRunnableAndExpectError(runnable, error); 178 verify(span).setStatus(Status.UNKNOWN.withDescription("AssertionError")); 179 verify(span).end(EndSpanOptions.DEFAULT); 180 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 181 } 182 183 @Test withSpanCallable()184 public void withSpanCallable() throws Exception { 185 final Object ret = new Object(); 186 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 187 Callable<Object> callable = 188 new Callable<Object>() { 189 @Override 190 public Object call() throws Exception { 191 // When we run the runnable we will have the span in the current Context. 192 assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); 193 return ret; 194 } 195 }; 196 assertThat(CurrentSpanUtils.withSpan(span, false, callable).call()).isEqualTo(ret); 197 verifyZeroInteractions(span); 198 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 199 } 200 201 @Test withSpanCallable_EndSpan()202 public void withSpanCallable_EndSpan() throws Exception { 203 final Object ret = new Object(); 204 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 205 Callable<Object> callable = 206 new Callable<Object>() { 207 @Override 208 public Object call() throws Exception { 209 // When we run the runnable we will have the span in the current Context. 210 assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); 211 return ret; 212 } 213 }; 214 assertThat(CurrentSpanUtils.withSpan(span, true, callable).call()).isEqualTo(ret); 215 verify(span).end(EndSpanOptions.DEFAULT); 216 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 217 } 218 219 @Test withSpanCallable_WithException()220 public void withSpanCallable_WithException() { 221 final Exception exception = new Exception("MyException"); 222 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 223 Callable<Object> callable = 224 new Callable<Object>() { 225 @Override 226 public Object call() throws Exception { 227 // When we run the runnable we will have the span in the current Context. 228 assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); 229 throw exception; 230 } 231 }; 232 executeCallableAndExpectError(callable, exception); 233 verify(span).setStatus(Status.UNKNOWN.withDescription("MyException")); 234 verify(span).end(EndSpanOptions.DEFAULT); 235 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 236 } 237 238 @Test withSpanCallable_WithExceptionNoMessage()239 public void withSpanCallable_WithExceptionNoMessage() { 240 final Exception exception = new Exception(); 241 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 242 Callable<Object> callable = 243 new Callable<Object>() { 244 @Override 245 public Object call() throws Exception { 246 // When we run the runnable we will have the span in the current Context. 247 assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); 248 throw exception; 249 } 250 }; 251 executeCallableAndExpectError(callable, exception); 252 verify(span).setStatus(Status.UNKNOWN.withDescription("Exception")); 253 verify(span).end(EndSpanOptions.DEFAULT); 254 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 255 } 256 257 @Test withSpanCallable_WithError()258 public void withSpanCallable_WithError() { 259 final AssertionError error = new AssertionError("MyError"); 260 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 261 Callable<Object> callable = 262 new Callable<Object>() { 263 @Override 264 public Object call() throws Exception { 265 // When we run the runnable we will have the span in the current Context. 266 assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); 267 throw error; 268 } 269 }; 270 executeCallableAndExpectError(callable, error); 271 verify(span).setStatus(Status.UNKNOWN.withDescription("MyError")); 272 verify(span).end(EndSpanOptions.DEFAULT); 273 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 274 } 275 276 @Test withSpanCallable_WithErrorNoMessage()277 public void withSpanCallable_WithErrorNoMessage() { 278 final AssertionError error = new AssertionError(); 279 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 280 Callable<Object> callable = 281 new Callable<Object>() { 282 @Override 283 public Object call() throws Exception { 284 // When we run the runnable we will have the span in the current Context. 285 assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); 286 throw error; 287 } 288 }; 289 executeCallableAndExpectError(callable, error); 290 verify(span).setStatus(Status.UNKNOWN.withDescription("AssertionError")); 291 verify(span).end(EndSpanOptions.DEFAULT); 292 assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); 293 } 294 } 295