test/jdk/tools/jlink/plugins/StripDebugPluginTest.java
changeset 53939 7f715085caac
parent 53938 c6b18dd94973
parent 53931 f47ca94f30b9
child 53940 f8b2179a55d0
equal deleted inserted replaced
53938:c6b18dd94973 53939:7f715085caac
     1 /*
       
     2  * Copyright (c) 2015, 2018, 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  * @summary Test StripDebugPlugin
       
    27  * @author Jean-Francois Denise
       
    28  * @library ../../lib
       
    29  * @build tests.*
       
    30  * @modules java.base/jdk.internal.jimage
       
    31  *          jdk.jlink/jdk.tools.jlink.internal
       
    32  *          jdk.jlink/jdk.tools.jlink.internal.plugins
       
    33  *          jdk.jlink/jdk.tools.jlink.plugin
       
    34  *          jdk.jlink/jdk.tools.jimage
       
    35  *          jdk.jlink/jdk.tools.jmod
       
    36  *          jdk.jdeps/com.sun.tools.classfile
       
    37  *          jdk.compiler
       
    38  * @run main StripDebugPluginTest
       
    39  */
       
    40 
       
    41 import java.io.ByteArrayInputStream;
       
    42 import java.io.IOException;
       
    43 import java.nio.file.Files;
       
    44 import java.nio.file.Path;
       
    45 import java.util.ArrayList;
       
    46 import java.util.Arrays;
       
    47 import java.util.Iterator;
       
    48 import java.util.List;
       
    49 import java.util.stream.Stream;
       
    50 
       
    51 import com.sun.tools.classfile.Attribute;
       
    52 import com.sun.tools.classfile.ClassFile;
       
    53 import com.sun.tools.classfile.Code_attribute;
       
    54 import com.sun.tools.classfile.ConstantPoolException;
       
    55 import com.sun.tools.classfile.Method;
       
    56 import java.util.HashMap;
       
    57 import java.util.Map;
       
    58 import jdk.tools.jlink.internal.ResourcePoolManager;
       
    59 import jdk.tools.jlink.internal.plugins.StripDebugPlugin;
       
    60 import jdk.tools.jlink.plugin.ResourcePoolEntry;
       
    61 import jdk.tools.jlink.plugin.ResourcePool;
       
    62 import jdk.tools.jlink.plugin.Plugin;
       
    63 import tests.Helper;
       
    64 
       
    65 public class StripDebugPluginTest {
       
    66     public static void main(String[] args) throws Exception {
       
    67         new StripDebugPluginTest().test();
       
    68     }
       
    69 
       
    70     public void test() throws Exception {
       
    71         Helper helper = Helper.newHelper();
       
    72         if (helper == null) {
       
    73             // Skip test if the jmods directory is missing (e.g. exploded image)
       
    74             System.err.println("Test not run, NO jmods directory");
       
    75             return;
       
    76         }
       
    77 
       
    78         List<String> classes = Arrays.asList("toto.Main", "toto.com.foo.bar.X");
       
    79         Path moduleFile = helper.generateModuleCompiledClasses(
       
    80                 helper.getJmodSrcDir(), helper.getJmodClassesDir(), "leaf1", classes);
       
    81         Path moduleInfo = moduleFile.resolve("module-info.class");
       
    82 
       
    83         // Classes have been compiled in debug.
       
    84         List<Path> covered = new ArrayList<>();
       
    85         byte[] infoContent = Files.readAllBytes(moduleInfo);
       
    86         try (Stream<Path> stream = Files.walk(moduleFile)) {
       
    87             for (Iterator<Path> iterator = stream.iterator(); iterator.hasNext(); ) {
       
    88                 Path p = iterator.next();
       
    89                 if (Files.isRegularFile(p) && p.toString().endsWith(".class")) {
       
    90                     byte[] content = Files.readAllBytes(p);
       
    91                     String path = "/" + helper.getJmodClassesDir().relativize(p).toString();
       
    92                     String moduleInfoPath = path + "/module-info.class";
       
    93                     check(path, content, moduleInfoPath, infoContent);
       
    94                     covered.add(p);
       
    95                 }
       
    96             }
       
    97         }
       
    98         if (covered.isEmpty()) {
       
    99             throw new AssertionError("No class to compress");
       
   100         } else {
       
   101             System.err.println("removed debug attributes from "
       
   102                     + covered.size() + " classes");
       
   103         }
       
   104     }
       
   105 
       
   106     private void check(String path, byte[] content, String infoPath, byte[] moduleInfo) throws Exception {
       
   107         path = path.replace('\\', '/');
       
   108         StripDebugPlugin debug = new StripDebugPlugin();
       
   109         debug.configure(new HashMap<>());
       
   110         ResourcePoolEntry result1 = stripDebug(debug, ResourcePoolEntry.create(path,content), path, infoPath, moduleInfo);
       
   111 
       
   112         if (!path.endsWith("module-info.class")) {
       
   113             if (result1.contentLength() >= content.length) {
       
   114                 throw new AssertionError("Class size not reduced, debug info not "
       
   115                         + "removed for " + path);
       
   116             }
       
   117             checkDebugAttributes(result1.contentBytes());
       
   118         }
       
   119 
       
   120         ResourcePoolEntry result2 = stripDebug(debug, result1, path, infoPath, moduleInfo);
       
   121         if (result1.contentLength() != result2.contentLength()) {
       
   122             throw new AssertionError("removing debug info twice reduces class size of "
       
   123                     + path);
       
   124         }
       
   125         checkDebugAttributes(result1.contentBytes());
       
   126     }
       
   127 
       
   128     private ResourcePoolEntry stripDebug(Plugin debug, ResourcePoolEntry classResource,
       
   129             String path, String infoPath, byte[] moduleInfo) throws Exception {
       
   130         ResourcePoolManager resources = new ResourcePoolManager();
       
   131         resources.add(classResource);
       
   132         if (!path.endsWith("module-info.class")) {
       
   133             ResourcePoolEntry res2 = ResourcePoolEntry.create(infoPath, moduleInfo);
       
   134             resources.add(res2);
       
   135         }
       
   136         ResourcePoolManager results = new ResourcePoolManager();
       
   137         ResourcePool resPool = debug.transform(resources.resourcePool(),
       
   138                 results.resourcePoolBuilder());
       
   139         System.out.println(classResource.path());
       
   140 
       
   141         return resPool.findEntry(classResource.path()).get();
       
   142     }
       
   143 
       
   144     private void checkDebugAttributes(byte[] strippedClassFile) throws IOException, ConstantPoolException {
       
   145         ClassFile classFile = ClassFile.read(new ByteArrayInputStream(strippedClassFile));
       
   146         String[] debugAttributes = new String[]{
       
   147                 Attribute.LineNumberTable,
       
   148                 Attribute.LocalVariableTable,
       
   149                 Attribute.LocalVariableTypeTable
       
   150         };
       
   151         for (Method method : classFile.methods) {
       
   152             String methodName = method.getName(classFile.constant_pool);
       
   153             Code_attribute code = (Code_attribute) method.attributes.get(Attribute.Code);
       
   154             for (String attr : debugAttributes) {
       
   155                 if (code.attributes.get(attr) != null) {
       
   156                     throw new AssertionError("Debug attribute was not removed: " + attr +
       
   157                             " from method " + classFile.getName() + "#" + methodName);
       
   158                 }
       
   159             }
       
   160         }
       
   161     }
       
   162 }