1 /*
   2  * Copyright (c) 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  * Asm plugin testing.
  26  * @test
  27  * @summary Test resource sorting.
  28  * @author Jean-Francois Denise
  29  * @modules jdk.jlink/jdk.tools.jlink.internal
  30  *          jdk.jlink/jdk.tools.jlink.internal.plugins.asm
  31  * @build AsmPluginTestBase
  32  * @run main SortingTest
  33  */
  34 
  35 import java.io.IOException;
  36 import java.util.ArrayList;
  37 import java.util.List;
  38 import java.util.Optional;
  39 import java.util.stream.Collectors;
  40 
  41 import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
  42 import jdk.tools.jlink.plugin.PluginException;
  43 import jdk.tools.jlink.plugin.ModuleEntry;
  44 import jdk.tools.jlink.plugin.ModulePool;
  45 
  46 public class SortingTest extends AsmPluginTestBase {
  47 
  48     public static void main(String[] args) throws Exception {
  49         if (!isImageBuild()) {
  50             System.err.println("Test not run. Not image build.");
  51             return;
  52         }
  53         new SortingTest().test();
  54     }
  55 
  56     @Override
  57     public void test() {
  58         try {
  59             classSorting();
  60             moduleSorting();
  61         } catch (Exception ex) {
  62             throw new PluginException(ex);
  63         }
  64     }
  65 
  66     private void classSorting() throws Exception {
  67         List<String> sorted = new ArrayList<>(getResources());
  68         sorted.sort(null);
  69         ClassSorterPlugin sorterPlugin = new ClassSorterPlugin(sorted);
  70         ModulePool resourcePool = sorterPlugin.visit(getPool());
  71         sorterPlugin.test(getPool(), resourcePool);
  72     }
  73 
  74     private String getModuleName(String p) {
  75         return p.substring(1, p.indexOf('/', 1));
  76     }
  77 
  78     private void moduleSorting() throws Exception {
  79         List<String> sorted = new ArrayList<>(getResources());
  80         sorted.sort((s1, s2) -> -getModuleName(s1).compareTo(getModuleName(s2)));
  81         ModuleSorterPlugin sorterPlugin = new ModuleSorterPlugin();
  82         ModulePool resourcePool = sorterPlugin.visit(getPool());
  83         sorterPlugin.test(getPool(), resourcePool);
  84     }
  85 
  86     private class ModuleSorterPlugin extends TestPlugin {
  87 
  88         @Override
  89         public void visit() {
  90             for (AsmModulePool modulePool : getPools().getModulePools()) {
  91                 modulePool.setSorter(resources -> {
  92                     List<String> sort = resources.entries()
  93                             .map(ModuleEntry::getPath)
  94                             .collect(Collectors.toList());
  95                     sort.sort(null);
  96                     return sort;
  97                 });
  98             }
  99             getPools().setModuleSorter(modules -> {
 100                 modules.sort((s1, s2) -> -s1.compareTo(s2));
 101                 return modules;
 102             });
 103         }
 104 
 105         @Override
 106         public void test(ModulePool inResources, ModulePool outResources) throws Exception {
 107             if (!isVisitCalled()) {
 108                 throw new AssertionError("Resources not visited");
 109             }
 110             List<String> sortedResourcePaths = outResources.entries()
 111                     .map(ModuleEntry::getPath)
 112                     .collect(Collectors.toList());
 113 
 114             List<String> defaultResourceOrder = new ArrayList<>();
 115             inResources.entries().forEach(r -> {
 116                 if (!inResources.contains(r)) {
 117                     throw new AssertionError("Resource " + r.getPath() + " not in result pool");
 118                 }
 119                 defaultResourceOrder.add(r.getPath());
 120             });
 121             // Check that default sorting is not equal to sorted one
 122             if (defaultResourceOrder.equals(sortedResourcePaths)) {
 123                 throw new AssertionError("Sorting not applied, default ordering");
 124             }
 125             // Check module order.
 126             for (int i = 0; i < sortedResourcePaths.size() - 1; ++i) {
 127                 String first = sortedResourcePaths.get(i);
 128                 String p1 = getModuleName(first);
 129                 String second = sortedResourcePaths.get(i + 1);
 130                 String p2 = getModuleName(second);
 131                 if (p1.compareTo(p2) < 0 || p1.compareTo(p2) == 0 &&
 132                         removeModule(first).compareTo(removeModule(second)) >= 0) {
 133                     throw new AssertionError("Modules are not sorted properly: resources: " + first + " " + second);
 134                 }
 135             }
 136         }
 137     }
 138 
 139     private class ClassSorterPlugin extends TestPlugin {
 140 
 141         private final List<String> expectedClassesOrder;
 142 
 143         private ClassSorterPlugin(List<String> expectedClassesOrder) {
 144             this.expectedClassesOrder = expectedClassesOrder;
 145         }
 146 
 147         @Override
 148         public void visit() {
 149             getPools().getGlobalPool().setSorter(
 150                     (resources) -> expectedClassesOrder.stream()
 151                             .map(resources::findEntry)
 152                             .map(Optional::get)
 153                             .map(ModuleEntry::getPath)
 154                             .collect(Collectors.toList()));
 155         }
 156 
 157         @Override
 158         public void test(ModulePool inResources, ModulePool outResources) throws Exception {
 159             if (!isVisitCalled()) {
 160                 throw new AssertionError("Resources not visited");
 161             }
 162             List<String> sortedResourcePaths = outResources.entries()
 163                     .map(ModuleEntry::getPath)
 164                     .collect(Collectors.toList());
 165 
 166             List<String> defaultResourceOrder = new ArrayList<>();
 167             getPool().entries().forEach(r -> {
 168                 if (!getPool().contains(r)) {
 169                     throw new AssertionError("Resource " + r.getPath() + " not in result pool");
 170                 }
 171                 defaultResourceOrder.add(r.getPath());
 172             });
 173             // Check that default sorting is not equal to sorted one
 174             if (defaultResourceOrder.equals(sortedResourcePaths)) {
 175                 throw new AssertionError("Sorting not applied, default ordering");
 176             }
 177             // Check that sorted is equal to result.
 178             if (!expectedClassesOrder.equals(sortedResourcePaths)) {
 179                 throw new AssertionError("Sorting not properly applied");
 180             }
 181         }
 182     }
 183 }