/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.tools.idea.logcat; import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.intellij.openapi.util.text.StringUtil; import junit.framework.TestCase; import java.util.ArrayList; import java.util.List; public class StackTraceExpanderTest extends TestCase { public void testExpander() { String input = "HighLevelException: MidLevelException: LowLevelException\n" + " at Junk.a(Junk.java:13)\n" + " at Junk.main(Junk.java:4)\n" + " Caused by: MidLevelException: LowLevelException\n" + " at Junk.c(Junk.java:23)\n" + " at Junk.b(Junk.java:17)\n" + " at Junk.a(Junk.java:11)\n" + " ... 1 more\n" + " Caused by: LowLevelException\n" + " at Junk.e(Junk.java:30)\n" + " at Junk.d(Junk.java:27)\n" + " at Junk.c(Junk.java:21)\n" + " ... 3 more\n"; String expectedOutput = "HighLevelException: MidLevelException: LowLevelException\n" + " at Junk.a(Junk.java:13)\n" + " at Junk.main(Junk.java:4)\n" + " Caused by: MidLevelException: LowLevelException\n" + " at Junk.c(Junk.java:23)\n" + " at Junk.b(Junk.java:17)\n" + " at Junk.a(Junk.java:11)\n" + " at Junk.main(Junk.java:4)\n" + " Caused by: LowLevelException\n" + " at Junk.e(Junk.java:30)\n" + " at Junk.d(Junk.java:27)\n" + " at Junk.c(Junk.java:21)\n" + " at Junk.b(Junk.java:17)\n" + " at Junk.a(Junk.java:11)\n" + " at Junk.main(Junk.java:4)\n"; test(input, expectedOutput); } public void testExpander2() { String input = "10-02 15:22:48.811 24985-24998/com.example.t1 E/e1﹕ error\n" + "java.lang.SecurityException: Permission denied (missing INTERNET permission?)\n" + " at java.net.InetAddress.lookupHostByName(InetAddress.java:418)\n" + " at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)\n" + " at java.net.InetAddress.getAllByName(InetAddress.java:214)\n" + " at java.lang.Thread.run(Thread.java:841)\n" + " Caused by: libcore.io.GaiException: getaddrinfo failed: EAI_NODATA (No address associated with hostname)\n" + " at java.net.InetAddress.lookupHostByName(InetAddress.java:405)\n" + " ... 2 more\n" + " Caused by: libcore.io.ErrnoException: getaddrinfo failed: EACCES (Permission denied)\n" + " ... 3 more\n"; String expected = "10-02 15:22:48.811 24985-24998/com.example.t1 E/e1﹕ error\n" + "java.lang.SecurityException: Permission denied (missing INTERNET permission?)\n" + " at java.net.InetAddress.lookupHostByName(InetAddress.java:418)\n" + " at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)\n" + " at java.net.InetAddress.getAllByName(InetAddress.java:214)\n" + " at java.lang.Thread.run(Thread.java:841)\n" + " Caused by: libcore.io.GaiException: getaddrinfo failed: EAI_NODATA (No address associated with hostname)\n" + " at java.net.InetAddress.lookupHostByName(InetAddress.java:405)\n" + " at java.net.InetAddress.getAllByName(InetAddress.java:214)\n" + " at java.lang.Thread.run(Thread.java:841)\n" + " Caused by: libcore.io.ErrnoException: getaddrinfo failed: EACCES (Permission denied)\n" + " at java.net.InetAddress.lookupHostByName(InetAddress.java:405)\n" + " at java.net.InetAddress.getAllByName(InetAddress.java:214)\n" + " at java.lang.Thread.run(Thread.java:841)\n"; test(input, expected); } private void test(String input, String expectedOutput) { StackTraceExpander expander = new StackTraceExpander( "", // don't add any extra prefixes StringUtil.repeatSymbol(' ', 9), // 9 spaces before at symbol in standard Java traces, used above StringUtil.repeatSymbol(' ', 11), // indent the expanded traces by 2 additional characters " "); // 1 space before "Caused by:" in the stack traces used above List<String> output = new ArrayList<String>(); for (String line: Splitter.on('\n').split(input)) { line = line.trim(); output.add(expander.expand(line)); } assertEquals(expectedOutput, Joiner.on('\n').join(output)); } public void testStackFrameMatcher() { String[] validFrames = new String[] { "at com.example.t1.MainActivity.one(MainActivity.java:31)", "at android.app.ActivityThread.access$700(ActivityThread.java:134)", "at java.lang.reflect.Method.invokeNative(Native Method)", }; for (String frame: validFrames) { assertTrue(StackTraceExpander.isStackFrame(frame)); } String[] invalidFrames = new String[] { "Caused by: java.lang.RuntimeException", "... 15 more" }; for (String frame: invalidFrames) { assertFalse(StackTraceExpander.isStackFrame(frame)); } } public void testElidedCount() { assertEquals(3, StackTraceExpander.getElidedFrameCount("... 3 more")); assertEquals(-1, StackTraceExpander.getElidedFrameCount("... more follow")); } }