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  *  @run build TestScaffold VMConnection TargetListener TargetAdapter
  31  *  @run compile -XDstringConcat=inline -g LineNumberInfo.java ControlFlow.java
  32  *
  33  *  @run driver LineNumberInfo
  34  */
  35 import com.sun.jdi.*;
  36 import com.sun.jdi.event.*;
  37 import com.sun.jdi.request.*;
  38 
  39 import java.util.List;
  40 import java.util.Iterator;
  41 
  42 public class LineNumberInfo extends TestScaffold {
  43     /*
  44      * These two arrays are used to validate the line number
  45      * information returned by JDI. There are limitations to
  46      * this approach:
  47      * - there are no strict rules about
  48      *   what constitutes the "right" line number mapping, so
  49      *   this kind of test may have false negatives with other
  50      *   compilers.
  51      * - this test is also sensitive to the compiler's code generation;
  52      *   if that changes, this test will likely need updating.
  53      * - this test assumes that JDI code index == class file
  54      *   byte code index which may not be true in all VMs.
  55      * - To find the values for these tables, compile ControlFlow.java and then
  56      *   do:
  57      *   javap -classpath _jj1.solaris-sparc/JTwork/classes/com/sun/jdi \
  58      *                    -l ControlFlow
  59      */
  60     final int[] lineNumbers = {
  61         15,
  62         16,
  63         19,
  64         20,
  65         22,
  66         25,
  67         26,
  68         28,
  69         32,
  70         33,
  71         34,
  72         36,
  73         37,
  74         36,
  75         40,
  76         41,
  77         42,
  78         45,
  79         46,
  80         45,
  81         49,
  82         51,
  83         53,
  84         55,
  85         57,
  86         59,
  87         60,
  88         62,
  89         65,
  90         67,
  91         69,
  92         71,
  93         73,
  94         75,
  95         78
  96     };
  97 
  98     final int[] codeIndices = {
  99         0  ,
 100         7  ,
 101         15 ,
 102         22 ,
 103         33 ,
 104         43 ,
 105         50 ,
 106         60 ,
 107         68 ,
 108         76 ,
 109         77 ,
 110         85 ,
 111         93 ,
 112         96 ,
 113         107,
 114         111,
 115         119,
 116         129,
 117         139,
 118         178,
 119         184,
 120         240,
 121         250,
 122         260,
 123         270,
 124         280,
 125         288,
 126         291,
 127         301,
 128         336,
 129         346,
 130         356,
 131         366,
 132         376,
 133         384
 134     };
 135 
 136     LineNumberInfo(String args[]) {
 137         super(args);
 138     }
 139 
 140     public static void main(String args[]) throws Exception {
 141         new LineNumberInfo(args).startTests();
 142     }
 143 
 144     protected void runTests() throws Exception {
 145         startUp("ControlFlow");
 146 
 147         // Get the ControlFlow class loaded.
 148         ClassPrepareEvent event = resumeToPrepareOf("ControlFlow");
 149 
 150         ClassType clazz = (ClassType)event.referenceType();
 151         Method method = clazz.concreteMethodByName("go", "()V");
 152         List locations = method.allLineLocations();
 153 
 154         if (lineNumbers.length != codeIndices.length) {
 155             failure("FAILED: Bad test. Line number and code index arrays " +
 156                  "must be equal in size");
 157         }
 158 
 159         if (locations.size() != codeIndices.length) {
 160             // Help the tester see why it failed.
 161             Iterator iter = locations.iterator();
 162             while (iter.hasNext()) {
 163                 Location location = (Location)iter.next();
 164                 System.err.println("location=" + location);
 165             }
 166 
 167             failure("FAILED: Bad line number table size: jdi=" +
 168                  locations.size() +
 169                  ", test=" + codeIndices.length);
 170         }
 171 
 172         int i = 0;
 173         Iterator iter = locations.iterator();
 174         while (iter.hasNext()) {
 175             Location location = (Location)iter.next();
 176             if (location.codeIndex() != codeIndices[i]) {
 177                 failure("FAILED: Code index mismatch: jdi=" +
 178                                     location.codeIndex() +
 179                                     ", test=" + codeIndices[i]);
 180             }
 181             if (location.lineNumber() != lineNumbers[i]) {
 182                 failure("FAILED: Line number mismatch: jdi=" +
 183                                     location.lineNumber() +
 184                                     ", test=" + lineNumbers[i]);
 185             }
 186             i++;
 187         }
 188 
 189 
 190         // Allow application to complete
 191         listenUntilVMDisconnect();
 192 
 193         /*
 194          * deal with results of test
 195          * if anything has called failure("foo") testFailed will be true
 196          */
 197         if (!testFailed) {
 198             println("LineNumberInfo: passed");
 199         } else {
 200             throw new Exception("LineNumberInfo: failed");
 201         }
 202 
 203     }
 204 }