| // Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 | package com.android.tools.r8.debuginfo; | 
 |  | 
 | import static org.junit.Assert.assertEquals; | 
 |  | 
 | import com.android.tools.r8.ToolHelper; | 
 | import com.android.tools.r8.utils.AndroidApp; | 
 | import org.junit.Test; | 
 |  | 
 | public class LocalsInSwitchTestRunner extends DebugInfoTestBase { | 
 |  | 
 |   @Test | 
 |   public void testLocalsInSwitch() throws Exception { | 
 |     Class clazz = LocalsInSwitchTest.class; | 
 |  | 
 |     AndroidApp d8App = compileWithD8(clazz); | 
 |     AndroidApp dxApp = getDxCompiledSources(); | 
 |  | 
 |     String expected = "55" + ToolHelper.LINE_SEPARATOR + "1862" + ToolHelper.LINE_SEPARATOR | 
 |             + "15130" + ToolHelper.LINE_SEPARATOR; | 
 |     assertEquals(expected, runOnJava(clazz)); | 
 |     assertEquals(expected, runOnArt(d8App, clazz.getCanonicalName())); | 
 |     assertEquals(expected, runOnArt(dxApp, clazz.getCanonicalName())); | 
 |  | 
 |     checkNoLocals(inspectMethod(d8App, clazz, "int", "noLocals", "int")); | 
 |     checkNoLocals(inspectMethod(dxApp, clazz, "int", "noLocals", "int")); | 
 |  | 
 |     checkTempInCase(inspectMethod(d8App, clazz, "int", "tempInCase", "int"), false); | 
 |     checkTempInCase(inspectMethod(dxApp, clazz, "int", "tempInCase", "int"), true); | 
 |  | 
 |     checkInitInCases(inspectMethod(d8App, clazz, "int", "initInCases", "int")); | 
 |     checkInitInCases(inspectMethod(dxApp, clazz, "int", "initInCases", "int")); | 
 |   } | 
 |  | 
 |   private void checkNoLocals(DebugInfoInspector info) { | 
 |     info.checkStartLine(9); | 
 |     info.checkLineHasExactLocals(9, "x", "int"); | 
 |     info.checkLineHasExactLocals(11, "x", "int"); | 
 |     info.checkLineHasExactLocals(13, "x", "int"); | 
 |     info.checkLineHasExactLocals(15, "x", "int"); | 
 |   } | 
 |  | 
 |   private void checkTempInCase(DebugInfoInspector tempInCase, boolean dx) { | 
 |     // int res = | 
 |     tempInCase.checkStartLine(20); | 
 |     tempInCase.checkLineHasExactLocals(20, "x", "int"); | 
 |     // for (int i = ... | 
 |     // The local 'i' is visible on the back edges, but not on the initial entry. | 
 |     tempInCase.checkLineHasAtLeastLocals(21, "x", "int", "res", "int"); | 
 |     //   int rem = | 
 |     tempInCase.checkLineHasExactLocals(22, "x", "int", "res", "int", "i", "int"); | 
 |     //   switch (rem) { | 
 |     if (!dx) { | 
 |       // DX contains several entries for 23, one of which does not define 'rem'. Go figure... | 
 |       tempInCase.checkLineHasExactLocals(23, "x", "int", "res", "int", "i", "int", "rem", "int"); | 
 |     } | 
 |     //   case 0: | 
 |     tempInCase.checkNoLine(24); | 
 |     //     return res | 
 |     if (!dx) { | 
 |       // DX does not produce a position at the return statement. Good stuff. | 
 |       tempInCase.checkLineHasExactLocals(25, "x", "int", "res", "int", "i", "int", "rem", "int"); | 
 |     } | 
 |     //   case 5: | 
 |     tempInCase.checkNoLine(26); | 
 |     //     int tmp = | 
 |     tempInCase.checkLineHasExactLocals(27, "x", "int", "res", "int", "i", "int", "rem", "int"); | 
 |     //     res += tmp | 
 |     tempInCase.checkLineHasExactLocals(28, | 
 |         "x", "int", "res", "int", "i", "int", "rem", "int", "tmp", "int"); | 
 |     //     break; | 
 |     tempInCase.checkLineHasExactLocals(29, | 
 |         "x", "int", "res", "int", "i", "int", "rem", "int", "tmp", "int"); | 
 |     //   case 10: | 
 |     tempInCase.checkNoLine(30); | 
 |     //     i++ | 
 |     tempInCase.checkLineHasExactLocals(31, "x", "int", "res", "int", "i", "int", "rem", "int"); | 
 |     //     break; | 
 |     tempInCase.checkLineHasExactLocals(32, "x", "int", "res", "int", "i", "int", "rem", "int"); | 
 |     //   default: | 
 |     tempInCase.checkNoLine(33); | 
 |     //     res += rem; | 
 |     tempInCase.checkLineHasExactLocals(34, "x", "int", "res", "int", "i", "int", "rem", "int"); | 
 |     //   } | 
 |     tempInCase.checkNoLine(35); | 
 |     //   res += rem % 2; | 
 |     tempInCase.checkLineHasExactLocals(36, "x", "int", "res", "int", "i", "int", "rem", "int"); | 
 |     // } | 
 |     tempInCase.checkNoLine(37); | 
 |     // res *= x; | 
 |     if (!dx) { | 
 |       // DX fails to end the scope of "i" after the loop. | 
 |       tempInCase.checkLineHasExactLocals(38, "x", "int", "res", "int"); | 
 |     } | 
 |     // return res; | 
 |     if (!dx) { | 
 |       tempInCase.checkLineHasExactLocals(39, "x", "int", "res", "int"); | 
 |     } | 
 |   } | 
 |  | 
 |   private void checkInitInCases(DebugInfoInspector info) { | 
 |     info.checkNoLine(43); // No line on uninitialized local declaration. | 
 |     info.checkStartLine(44); | 
 |     info.checkLineHasExactLocals(44, "x", "int"); // Local "res" is still not visible in the case. | 
 |     info.checkLineHasExactLocals(46, "x", "int"); // Ditto. | 
 |     info.checkLineHasExactLocals(48, "x", "int"); // Ditto. | 
 |     info.checkLineHasExactLocals(51, "x", "int"); // Ditto. | 
 |     info.checkLineHasExactLocals(53, "x", "int", "res", "java.lang.Integer"); | 
 |   } | 
 | } |