1 /*
   2  * Copyright (c) 2016, 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 8049365
  27  * @summary Tests the JDI and JDWP update for modules
  28  *
  29  * @run build TestScaffold VMConnection TargetListener TargetAdapter
  30  * @run compile -g ModulesTest.java
  31  * @run driver ModulesTest
  32  */
  33 import com.sun.jdi.*;
  34 import com.sun.jdi.event.*;
  35 import com.sun.jdi.request.*;
  36 
  37 import java.util.*;
  38 
  39     /********** target program **********/
  40 
  41 class ModulesTarg {
  42 
  43     public static void main(String[] args){
  44         System.out.println("Goodbye from ModulesTarg!");
  45     }
  46 }
  47 
  48     /********** test program **********/
  49 
  50 public class ModulesTest extends TestScaffold {
  51     static final String FailPrefix = "ModulesTest: failed: ";
  52 
  53     private static ModuleReference bootUnnamedModule = null;
  54     private static ModuleReference appUnnamedModule  = null;
  55     private static ModuleReference extUnnamedModule  = null;
  56 
  57     private ReferenceType targetClass;
  58     private List<ModuleReference> modules;
  59 
  60 
  61     ModulesTest (String args[]) {
  62         super(args);
  63     }
  64 
  65     public static void main(String[] args) throws Exception {
  66         new ModulesTest(args).startTests();
  67     }
  68 
  69     /********** test core **********/
  70 
  71     private boolean reftypeSanityCheck(ModuleReference module, ReferenceType type) {
  72         ModuleReference other = type.module();
  73         if (other == null) {
  74             testFailed = true;
  75             println(FailPrefix + "a ModuleReference should never be null #1");
  76             return false;
  77         }
  78         // Sanity checks: make sure there is no crash or exception
  79         String otherName = other.name();
  80         return true;
  81     }
  82 
  83     private void checkLoaderDefinedClasses(ModuleReference module, ClassLoaderReference loader) {
  84         String moduleName = module.name();
  85         List<ReferenceType> definedClasses = loader.definedClasses();
  86         boolean origModuleWasObserved = false;
  87 
  88         for (ReferenceType type: definedClasses) {
  89             ClassLoaderReference otherLoader = type.classLoader();
  90             if (!loader.equals(otherLoader)) {
  91                 testFailed = true;
  92                 println(FailPrefix + "all classes defined by a ClassLoader" +
  93                         " should refer to the defining ClassLoader");
  94                 return;
  95             }
  96             if (!reftypeSanityCheck(module, type)) {
  97                 return;
  98             }
  99         }
 100     }
 101 
 102     private void checkLoaderVisibleClasses(ModuleReference module, ClassLoaderReference loader) {
 103         String moduleName = module.name();
 104         List<ReferenceType> visibleClasses = loader.visibleClasses();
 105 
 106         for (ReferenceType type: visibleClasses) {
 107             if (!type.isPrepared()) {
 108                 continue; // Safety: skip unprepared classes
 109             }
 110             if (!reftypeSanityCheck(module, type)) {
 111                 return;
 112             }
 113         }
 114     }
 115 
 116     // Check any ClassLoader except the bootsrtap ClassLoader
 117     private void checkClassLoader(ModuleReference module, ClassLoaderReference loader) {
 118         checkLoaderDefinedClasses(module, loader);
 119         checkLoaderVisibleClasses(module, loader);
 120     }
 121 
 122     // Sanity checks to make sure there are no crashes or exceptions.
 123     private void checkModule(ModuleReference module, ModuleReference other, int checkIdx) {
 124         if (module == null) {
 125             testFailed = true;
 126             println(FailPrefix + "a ModuleReference should never be null #2");
 127             return;
 128         }
 129         String name = module.name();
 130         println("\n--- Check #" + checkIdx);
 131         println("    module name: " + name);
 132 
 133         ClassLoaderReference loader = module.classLoader();
 134         println("    loader: " + loader);
 135 
 136         if (loader != null) {
 137             checkClassLoader(module, loader);
 138             String classloaderName = loader.toString();
 139             if (classloaderName.contains("AppClassLoader") && name == null) {
 140                 if (appUnnamedModule != null) {
 141                     testFailed = true;
 142                     println(FailPrefix + "multiple unnamed modules in AppClassLoader");
 143                 }
 144                 appUnnamedModule = module;
 145             }
 146             if (classloaderName.contains("PlatformClassLoader") && name == null) {
 147                 if (extUnnamedModule != null) {
 148                     testFailed = true;
 149                     println(FailPrefix + "multiple unnamed modules in PlatformClassLoader");
 150                 }
 151                 extUnnamedModule = module;
 152             }
 153         } else if (name == null) {
 154             if (bootUnnamedModule != null) {
 155                 testFailed = true;
 156                 println(FailPrefix + "multiple unnamed modules in BootClassLoader");
 157             }
 158             bootUnnamedModule = module;
 159         }
 160     }
 161 
 162     // Check that the java.lang.String class was loaded by the java.base module.
 163     private void checkBaseModule() {
 164         List<ReferenceType> clist = vm().classesByName("java.lang.String");
 165         if (clist.size() != 1) {
 166             testFailed = true;
 167             println(FailPrefix + "just one java.lang.String class is expected" +
 168                     "but found multiple class instances: " + clist.size());
 169             return;
 170         }
 171         ModuleReference module = clist.get(0).module();
 172         if (module == null) {
 173             testFailed = true;
 174             println(FailPrefix + "a ModuleReference should never be null #3");
 175         }
 176         if (module.name().compareTo("java.base") != 0) {
 177             testFailed = true;
 178             println(FailPrefix + "java.lang.String must belong to java.base module");
 179         }
 180     }
 181 
 182     // Check that the unnamed modules of the bootsrtap, application
 183     // and platform class loaders were observed.
 184     private void checkUnnamedModules() {
 185         if (bootUnnamedModule == null) {
 186             testFailed = true;
 187             println(FailPrefix + "unnamed module of BootClassLoader was not observed");
 188         }
 189         if (appUnnamedModule == null) {
 190             testFailed = true;
 191             println(FailPrefix + "unnamed module of AppClassLoader was not observed");
 192         }
 193         if (extUnnamedModule == null) {
 194             testFailed = true;
 195             println(FailPrefix + "unnamed module of PlatformClassLoader was not observed");
 196         }
 197     }
 198 
 199     protected void runTests() throws Exception {
 200         /*
 201          * Get to the top of main() to determine targetClass
 202          */
 203         BreakpointEvent bpe = startToMain("ModulesTarg");
 204         targetClass = bpe.location().declaringType();
 205 
 206         if (!vm().canGetModuleInfo()) {
 207             testFailed = true;
 208             println(FailPrefix + "vm().canGetModuleInfo() returned false");
 209         }
 210         ModuleReference other = targetClass.module();
 211         modules = vm().allModules();
 212 
 213         int checkIdx = 0;
 214 
 215         for (ModuleReference module : modules) {
 216             checkModule(module, other, checkIdx++);
 217             other = module;
 218         }
 219 
 220         checkBaseModule();
 221         checkUnnamedModules();
 222 
 223         /*
 224          * resume the target until end
 225          */
 226         listenUntilVMDisconnect();
 227 
 228         /*
 229          * deal with results of test
 230          * if anything has called failure("foo") testFailed will be true
 231          */
 232         if (!testFailed) {
 233             println("ModulesTest: passed");
 234         } else {
 235             throw new Exception("ModulesTest: some checks failed");
 236         }
 237     }
 238 }