1 /*
   2  * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  *  @test
  26  *  @bug 4238644 4238643 4238641 4944198
  27  *  @summary Test javac regressions in the generation of line number info
  28  *  @author Gordon Hirsch
  29  *
  30  *  @modules jdk.jdi
  31  *  @run build TestScaffold VMConnection TargetListener TargetAdapter
  32  *  @run compile -XDstringConcat=inline -g LineNumberInfo.java ControlFlow.java
  33  *
  34  *  @run driver LineNumberInfo
  35  */
  36 import com.sun.jdi.*;
  37 import com.sun.jdi.event.*;
  38 import com.sun.jdi.request.*;
  39 
  40 import java.util.List;
  41 import java.util.Iterator;
  42 
  43 public class LineNumberInfo extends TestScaffold {
  44     /*
  45      * These two arrays are used to validate the line number
  46      * information returned by JDI. There are limitations to
  47      * this approach:
  48      * - there are no strict rules about
  49      *   what constitutes the "right" line number mapping, so
  50      *   this kind of test may have false negatives with other
  51      *   compilers.
  52      * - this test is also sensitive to the compiler's code generation;
  53      *   if that changes, this test will likely need updating.
  54      * - this test assumes that JDI code index == class file
  55      *   byte code index which may not be true in all VMs.
  56      * - To find the values for these tables, compile ControlFlow.java and then
  57      *   do:
  58      *   javap -classpath _jj1.solaris-sparc/JTwork/classes/com/sun/jdi \
  59      *                    -l ControlFlow
  60      */
  61     final int[] lineNumbers = {
  62         15,
  63         16,
  64         19,
  65         20,
  66         22,
  67         25,
  68         26,
  69         28,
  70         32,
  71         33,
  72         34,
  73         36,
  74         37,
  75         36,
  76         40,
  77         41,
  78         42,
  79         45,
  80         46,
  81         45,
  82         49,
  83         51,
  84         53,
  85         55,
  86         57,
  87         59,
  88         60,
  89         62,
  90         65,
  91         67,
  92         69,
  93         71,
  94         73,
  95         75,
  96         78
  97     };
  98 
  99     final int[] codeIndices = {
 100         0  ,
 101         7  ,
 102         15 ,
 103         22 ,
 104         33 ,
 105         43 ,
 106         50 ,
 107         60 ,
 108         68 ,
 109         76 ,
 110         77 ,
 111         85 ,
 112         93 ,
 113         96 ,
 114         107,
 115         111,
 116         119,
 117         129,
 118         139,
 119         178,
 120         184,
 121         240,
 122         250,
 123         260,
 124         270,
 125         280,
 126         288,
 127         291,
 128         301,
 129         336,
 130         346,
 131         356,
 132         366,
 133         376,
 134         384
 135     };
 136 
 137     LineNumberInfo(String args[]) {
 138         super(args);
 139     }
 140 
 141     public static void main(String args[]) throws Exception {
 142         new LineNumberInfo(args).startTests();
 143     }
 144 
 145     protected void runTests() throws Exception {
 146         startUp("ControlFlow");
 147 
 148         // Get the ControlFlow class loaded.
 149         ClassPrepareEvent event = resumeToPrepareOf("ControlFlow");
 150 
 151         ClassType clazz = (ClassType)event.referenceType();
 152         Method method = clazz.concreteMethodByName("go", "()V");
 153         List locations = method.allLineLocations();
 154 
 155         if (lineNumbers.length != codeIndices.length) {
 156             failure("FAILED: Bad test. Line number and code index arrays " +
 157                  "must be equal in size");
 158         }
 159 
 160         if (locations.size() != codeIndices.length) {
 161             // Help the tester see why it failed.
 162             Iterator iter = locations.iterator();
 163             while (iter.hasNext()) {
 164                 Location location = (Location)iter.next();
 165                 System.err.println("location=" + location);
 166             }
 167 
 168             failure("FAILED: Bad line number table size: jdi=" +
 169                  locations.size() +
 170                  ", test=" + codeIndices.length);
 171         }
 172 
 173         int i = 0;
 174         Iterator iter = locations.iterator();
 175         while (iter.hasNext()) {
 176             Location location = (Location)iter.next();
 177             if (location.codeIndex() != codeIndices[i]) {
 178                 failure("FAILED: Code index mismatch: jdi=" +
 179                                     location.codeIndex() +
 180                                     ", test=" + codeIndices[i]);
 181             }
 182             if (location.lineNumber() != lineNumbers[i]) {
 183                 failure("FAILED: Line number mismatch: jdi=" +
 184                                     location.lineNumber() +
 185                                     ", test=" + lineNumbers[i]);
 186             }
 187             i++;
 188         }
 189 
 190 
 191         // Allow application to complete
 192         listenUntilVMDisconnect();
 193 
 194         /*
 195          * deal with results of test
 196          * if anything has called failure("foo") testFailed will be true
 197          */
 198         if (!testFailed) {
 199             println("LineNumberInfo: passed");
 200         } else {
 201             throw new Exception("LineNumberInfo: failed");
 202         }
 203 
 204     }
 205 }