AndroidRuntime implements RuntimeDialect { @Override public StackTraceElement getCallerStackTraceElement(final int depth) { StackTraceElement[] trace = extractCallerStackTraceElements(depth + stackTraceOffset + 1); return trace == null ? new Throwable().getStackTrace()[depth] : trace[trace.length - 1]; } AndroidRuntime(); @Override boolean isAndroid(); @Override String getDefaultWriter(); @Override long getProcessId(); @Override Timestamp getStartTime(); @Override String getCallerClassName(final int depth); @Override String getCallerClassName(final String loggerClassName); @Override StackTraceElement getCallerStackTraceElement(final int depth); @Override StackTraceElement getCallerStackTraceElement(final String loggerClassName); @Override Timestamp createTimestamp(); @Override TimestampFormatter createTimestampFormatter(final String pattern, final Locale locale);  }
@Test public void callerStackTraceElementByIndex() { AndroidRuntime runtime = new AndroidRuntime(); Method method = Whitebox.getMethod(AndroidRuntimeTest.class, "fillStackTraceElements", Thread.class, StackTraceElement[].class); Whitebox.setInternalState(runtime, Method.class, method); Whitebox.setInternalState(runtime, int.class, 5); assertThat(runtime.getCallerStackTraceElement(1)).isEqualTo(new Throwable().getStackTrace()[0]); }
@Test public void callerStackTraceElementBySuccessor() { AndroidRuntime runtime = new AndroidRuntime(); Method method = Whitebox.getMethod(AndroidRuntimeTest.class, "fillStackTraceElements", Thread.class, StackTraceElement[].class); Whitebox.setInternalState(runtime, Method.class, method); Whitebox.setInternalState(runtime, int.class, 5); assertThat(runtime.getCallerStackTraceElement(AndroidRuntime.class.getName())).isEqualTo(new Throwable().getStackTrace()[0]); }
@Test public void missingSuccessorForCallerStackTraceElement() { AndroidRuntime runtime = new AndroidRuntime(); Method method = Whitebox.getMethod(AndroidRuntimeTest.class, "fillStackTraceElements", Thread.class, StackTraceElement[].class); Whitebox.setInternalState(runtime, Method.class, method); Whitebox.setInternalState(runtime, int.class, 5); assertThatThrownBy(() -> runtime.getCallerStackTraceElement(Logger.class.getName())) .isInstanceOf(IllegalStateException.class) .hasMessageContaining(Logger.class.getName()); }
@Test public void missingStackTraceElementsFiller() { AndroidRuntime runtime = new AndroidRuntime(); Whitebox.setInternalState(runtime, Method.class, (Object) null); Whitebox.setInternalState(runtime, int.class, -1); assertThat(new AndroidRuntime().getCallerStackTraceElement(1)).isEqualTo(new Throwable().getStackTrace()[0]); assertThat(runtime.getCallerStackTraceElement(AndroidRuntime.class.getName())).isEqualTo(new Throwable().getStackTrace()[0]); }
@Test public void notAccessibleStackTraceElementsFiller() { AndroidRuntime runtime = new AndroidRuntime(); Method method = Whitebox.getMethod(AndroidRuntimeTest.class, "fillStackTraceElements", Thread.class, StackTraceElement[].class); method.setAccessible(false); Whitebox.setInternalState(runtime, Method.class, method); Whitebox.setInternalState(runtime, int.class, 5); assertThat(runtime.getCallerStackTraceElement(1)).isEqualTo(new Throwable().getStackTrace()[0]); assertThat(systemStream.consumeErrorOutput()) .containsOnlyOnce("ERROR") .containsOnlyOnce(IllegalAccessException.class.getName()); }
@Test public void stackTraceElementsFillerThrowsException() { AndroidRuntime runtime = new AndroidRuntime(); Method method = Whitebox.getMethod(AndroidRuntimeTest.class, "throwException", Thread.class, StackTraceElement[].class); Whitebox.setInternalState(runtime, Method.class, method); Whitebox.setInternalState(runtime, int.class, 5); assertThat(runtime.getCallerStackTraceElement(1)).isEqualTo(new Throwable().getStackTrace()[0]); assertThat(systemStream.consumeErrorOutput()) .containsOnlyOnce("ERROR") .containsOnlyOnce(UnsupportedOperationException.class.getName()); }