• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
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 com.android.tools.r8;
18 
19 import java.io.BufferedReader;
20 import java.io.InputStream;
21 import java.io.InputStreamReader;
22 import java.nio.charset.StandardCharsets;
23 import java.util.List;
24 import java.util.stream.Collectors;
25 import org.junit.Assert;
26 import org.junit.Test;
27 
28 public class CheckRetracedStacktraceTest {
29 
30   private static final String FRAME_PREFIX =
31       "    at com.example.android.helloactivitywithr8.HelloActivityWithR8.";
32 
getResourceLines(String resource)33   private List<String> getResourceLines(String resource) throws Exception {
34     try (InputStream is = getClass().getResourceAsStream(resource)) {
35       return new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))
36           .lines()
37           .collect(Collectors.toList());
38     }
39   }
40 
onErrorDebugInfo()41   private String onErrorDebugInfo() throws Exception {
42     StringBuilder builder = new StringBuilder("\nAdditional debug info:\n");
43     appendResourceContent(builder, "dexdump.txt");
44     appendResourceContent(builder, "proguard_dictionary");
45     appendResourceContent(builder, "stacktrace.txt");
46     appendResourceContent(builder, "retraced-stacktrace.txt");
47     return builder.toString();
48   }
49 
appendResourceContent(StringBuilder builder, String resource)50   private void appendResourceContent(StringBuilder builder, String resource) throws Exception {
51     builder.append("==== ").append(resource).append('\n');
52     getResourceLines("/" + resource).forEach(l -> builder.append(l).append('\n'));
53   }
54 
55   @Test
checkRawStacktrace()56   public void checkRawStacktrace() throws Exception {
57     String errorInfo = onErrorDebugInfo();
58 
59     List<String> lines = getResourceLines("/stacktrace.txt");
60     // In release builds a single frame is present, in debug builds two.
61     Assert.assertTrue(errorInfo, 1 < lines.size() && lines.size() <= 3);
62     Assert.assertEquals(errorInfo, "java.lang.RuntimeException: error", lines.get(0));
63     // The frame lines "at line" is the qualified method and we don't check build hash
64     // and PC to allow minor changes to the test app and compiler without breaking this test.
65     for (int i = 1; i < lines.size(); i++) {
66       String frameLine = lines.get(i);
67       int sourceFileStart = frameLine.indexOf('(');
68       int lineNumberSeparator = frameLine.indexOf(':');
69       int lineNumberEnd = frameLine.lastIndexOf(')');
70       int hashInfoSeparator = frameLine.lastIndexOf(' ', lineNumberSeparator);
71       Assert.assertTrue(errorInfo, frameLine.startsWith(FRAME_PREFIX));
72       Assert.assertEquals(
73           errorInfo, "(go/retraceme", frameLine.substring(sourceFileStart, hashInfoSeparator));
74       String lineNumberString = frameLine.substring(lineNumberSeparator + 1, lineNumberEnd);
75       try {
76         int lineNumber = Integer.parseInt(lineNumberString);
77       } catch (NumberFormatException e) {
78         Assert.fail("Invalid line number: " + lineNumberString + errorInfo);
79       }
80     }
81   }
82 
83   @Test
checkRetracedStacktrace()84   public void checkRetracedStacktrace() throws Exception {
85     String errorInfo = onErrorDebugInfo();
86 
87     // Prefix is the qualified class on each line, suffix does not check line numbers to
88     // allow minor changes to the test app without breaking this test.
89     String suffix = "(HelloActivityWithR8.java";
90 
91     List<String> lines = getResourceLines("/retraced-stacktrace.txt");
92     int expectedLines = 3;
93     Assert.assertEquals(
94         "Expected "
95             + expectedLines
96             + " lines, got: \n=====\n"
97             + String.join("\n", lines)
98             + "\n====="
99             + errorInfo,
100         expectedLines,
101         lines.size());
102     Assert.assertEquals(errorInfo, "java.lang.RuntimeException: error", lines.get(0));
103     String line1 = lines.get(1);
104     Assert.assertEquals(
105         errorInfo, FRAME_PREFIX + "getView" + suffix, line1.substring(0, line1.indexOf(':')));
106     String line2 = lines.get(2);
107     Assert.assertEquals(
108         errorInfo, FRAME_PREFIX + "onCreate" + suffix, line2.substring(0, line2.indexOf(':')));
109   }
110 }
111