Mercurial > hg > jdk9-shenandoah > jdk
view test/jdk/internal/jimage/JImageReadTest.java @ 12737:d7f0c840a572
8087181: Move native jimage code to its own library (maybe libjimage)
Reviewed-by: alanb, lfoltan, hseigel, acorn
Contributed-by: james.laskey@oracle.com, jean-francois.denise@oracle.com, roger.riggs@oracle.com
author | jlaskey |
---|---|
date | Fri, 04 Sep 2015 10:11:43 -0300 |
parents | |
children |
line wrap: on
line source
/* * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @modules java.base/jdk.internal.jimage * @summary Unit test for libjimage JIMAGE_Open/Read/Close */ import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.nio.ByteBuffer; import java.util.Arrays; import jdk.internal.jimage.BasicImageReader; import jdk.internal.jimage.ImageNativeSubstrate; import org.testng.annotations.DataProvider; import org.testng.annotations.Optional; import org.testng.annotations.Parameters; import org.testng.annotations.Test; import org.testng.Assert; import org.testng.TestNG; @Test public class JImageReadTest { static String javaHome = System.getProperty("java.home"); static String imageFile = javaHome + File.separator + "lib" + File.separator + "modules" + File.separator + "bootmodules.jimage"; @DataProvider(name="classes") static Object[][] loadClasses() { return new Object[][] { {"java.base", "java/lang/String.class"}, {"java.base", "java/lang/Object.class"}, {"java.base", "sun/reflect/generics/tree/TypeArgument.class"}, {"jdk.jdeps", "com/sun/tools/javap/StackMapWriter$StackMapBuilder.class"}, {"jdk.hotspot.agent", "sa.properties"}, {"java.logging", "java/util/logging/Logger.class"}, {"java.base", "java/NOSUCHCLASS/yyy.class"}, // non-existent {"NOSUCHMODULE", "java/lang/Class.class"}, // non-existent }; } @DataProvider(name="packages") static Object[][] loadPackages() { return new Object[][] { {"java.base", "java/lang"}, {"java.base", "java/io"}, {"java.logging", "java/util/logging"}, }; } /** * Test a class is correctly accessible from the image in a module. * * @param moduleName the module name * @param className the classname * @throws Exception is thrown if there is a test error */ @Test(dataProvider="classes") public static void test1_ReadClasses(String moduleName, String className) throws Exception { final int classMagic = 0xCAFEBABE; final long NOT_FOUND = 0L; if (!(new File(imageFile)).exists()) { System.out.printf("Test skipped; no jimage file"); return; } long jimageHandle = ImageNativeSubstrate.JIMAGE_Open(imageFile); Assert.assertTrue(jimageHandle != 0, "JIMAGE_Open failed: id: " + jimageHandle); long[] sizeArray = new long[1]; long locationHandle = ImageNativeSubstrate.JIMAGE_FindResource(jimageHandle, moduleName, "9.0", className, sizeArray); long size = sizeArray[0]; System.out.printf("reading: module: %s, path: %s, handle: %16x, " + "location: %d, size: %d%n", moduleName, className, jimageHandle, locationHandle, size); if (moduleName.contains("NOSUCH") || className.contains("NOSUCH")) { Assert.assertEquals(locationHandle, NOT_FOUND, "location found for non-existing module: " + moduleName + ", or class: " + className); return; // no more to test for non-existing class } else { Assert.assertTrue(locationHandle != NOT_FOUND, "location not found: " + className); Assert.assertTrue(size > 0, "size of should be > 0: " + className); } // positive: read whole class ByteBuffer buffer = ByteBuffer.allocate((int)size); long actual = ImageNativeSubstrate.JIMAGE_GetResource(jimageHandle, locationHandle, buffer.array(), size); Assert.assertEquals(actual, size, "bytes read not equal bytes requested"); if (className.endsWith(".class")) { int m = buffer.getInt(); Assert.assertEquals(m, classMagic, "Classfile has bad magic number"); } // Read less than the size of the artifact buffer.rewind(); Arrays.fill(buffer.array(), (byte)0xc0); long sizeExpected = size - 10; actual = ImageNativeSubstrate.JIMAGE_GetResource(jimageHandle, locationHandle, buffer.array(), sizeExpected); Assert.assertEquals(actual, sizeExpected, "bytes read not equal bytes requested"); if (className.endsWith(".class")) { int m1 = buffer.getInt(); Assert.assertEquals(m1, classMagic, "Read operation succeeded but has bad magic number"); } ImageNativeSubstrate.JIMAGE_Close(jimageHandle); } /** * For all the resource names, check the name and approximate count. * * @throws IOException thrown if an error occurs */ @Test static void test2_ImageResources() throws IOException { if (!(new File(imageFile)).exists()) { System.out.printf("Test skipped; no jimage file"); return; } long jimageHandle = ImageNativeSubstrate.JIMAGE_Open(imageFile); Assert.assertTrue(jimageHandle != 0, "JIMAGE_Open failed: id: " + jimageHandle); String[] names = new String[4096]; int max = ImageNativeSubstrate.JIMAGE_Resources(jimageHandle, names); // Repeat with count available names = new String[max + 1]; int count = ImageNativeSubstrate.JIMAGE_Resources(jimageHandle, names); System.out.printf(" count: %d, a class: %s\n", count, names[0]); Assert.assertTrue(max > 31000, "missing entries, should be more than 31000, reported: " + count); Assert.assertTrue(count == max, "unexpected count of entries, count: " + count + ", max: " + max); for (int i = 0; i < count; i++) { checkFullName(names[i]); } ImageNativeSubstrate.JIMAGE_Close(jimageHandle); } /** * Tests that a package exists and correctly mapped to the module. * * @param moduleName the module name * @param packageName the package name * @throws IOException thrown if an error occurs */ @Test(dataProvider="packages") static void test3_PackageToModule(String moduleName, String packageName) throws IOException { if (!(new File(imageFile)).exists()) { System.out.printf("Test skipped; no jimage file"); return; } long jimageHandle = ImageNativeSubstrate.JIMAGE_Open(imageFile); Assert.assertTrue(jimageHandle != 0, "JIMAGE_Open failed: id: " + jimageHandle); String result = ImageNativeSubstrate.JIMAGE_PackageToModule(jimageHandle, packageName); System.out.printf(" package: %s, module: %s%n", packageName, result); Assert.assertEquals(result, moduleName, "wrong module for package: " + packageName); ImageNativeSubstrate.JIMAGE_Close(jimageHandle); } static void checkFullName(String path) { int next = 0; String m = null; String p = null; String b = null; String e = null; if (path.startsWith("/")) { next = path.indexOf('/', 1); m = path.substring(1, next); next = next + 1; } int lastSlash = path.lastIndexOf('/'); if (lastSlash > next) { // has a parent p = path.substring(next, lastSlash); next = lastSlash + 1; } int period = path.indexOf('.', next); if (period > next) { b = path.substring(next, period); e = path.substring(period + 1); } else { b = path.substring(next); } Assert.assertNotNull(m, "module must be non-empty"); Assert.assertNotNull(b, "base name must be non-empty"); } /** * Verify that all of the resource names from BasicImageReader * match those returned from the native JIMAGE_Resources iterator. * Names that start with /modules, /packages, and bootmodules.jdata * must appear in the names from JIMAGE_Resource iterator; * from the BasicImageReader they are ignored. */ @Test static void test4_verifyNames() { if (!(new File(imageFile)).exists()) { System.out.printf("Test skipped; no jimage file"); return; } try { String[] names = BasicImageReader_Names(); //writeNames("/tmp/basic-names.txt", names); // debug // Read all the names from the native JIMAGE API String[] nativeNames = JIMAGE_Names(); //writeNames("/tmp/native-names.txt", nativeNames); // debug int modCount = 0; int pkgCount = 0; int otherCount = 0; for (String n : nativeNames) { if (n.startsWith("/modules/")) { modCount++; } else if (n.startsWith("/packages/")) { pkgCount++; } else { otherCount++; } } System.out.printf("native name count: %d, modCount: %d, pkgCount: %d, otherCount: %d%n", names.length, modCount, pkgCount, otherCount); Assert.assertEquals(modCount, 0, "JIMAGE_ResourceIterator should not return any '/modules' paths"); Assert.assertEquals(pkgCount, 0, "JIMAGE_ResourceIterator should not return any '/packages' paths"); // Sort and merge the two arrays. Every name should appear exactly twice. Arrays.sort(names); Arrays.sort(nativeNames); String[] combined = Arrays.copyOf(names, nativeNames.length + names.length); System.arraycopy(nativeNames,0, combined, names.length, nativeNames.length); Arrays.sort(combined); int missing = 0; for (int i = 0; i < combined.length; i++) { String s = combined[i]; if (isMetaName(s)) { // Ignore /modules and /packages in BasicImageReader names continue; } if (i < combined.length - 1 && s.equals(combined[i + 1])) { i++; // string appears in both java and native continue; } missing++; int ndx = Arrays.binarySearch(names, s); String which = (ndx >= 0) ? "java BasicImageReader" : "native JIMAGE_Resources"; System.out.printf("Missing Resource: %s found only via %s%n", s, which); } Assert.assertEquals(missing, 0, "Resources missing"); } catch (IOException ioe) { Assert.fail("I/O exception", ioe); } } /** * Return true if the name is one of the meta-data names * @param name a name * @return return true if starts with either /packages or /modules */ static boolean isMetaName(String name) { return name.startsWith("/modules") || name.startsWith("/packages") || name.equals("bootmodules.jdata"); } /** * Return all of the names from BasicImageReader. * @return the names returned from BasicImageReader */ static String[] BasicImageReader_Names() throws IOException { String[] names = null; try (BasicImageReader reader = BasicImageReader.open(imageFile)) { names = reader.getEntryNames(); } catch (IOException ioe) { Assert.fail("I/O exception", ioe); } return names; } /** * Returns an array of all of the names returned from JIMAGE_Resources */ static String[] JIMAGE_Names() throws IOException { long jimageHandle = ImageNativeSubstrate.JIMAGE_Open(imageFile); Assert.assertTrue(jimageHandle != 0, "JIMAGE_Open failed: id: " + jimageHandle); String[] names = new String[50000]; int max = ImageNativeSubstrate.JIMAGE_Resources(jimageHandle, names); if (max > names.length) { // Not all names fit, repeat with correct size names = new String[max]; max = ImageNativeSubstrate.JIMAGE_Resources(jimageHandle, names); } else { names = Arrays.copyOf(names, max); } ImageNativeSubstrate.JIMAGE_Close(jimageHandle); return names; } // Write an array of names to a file for debugging static void writeNames(String fname, String[] names) throws IOException { try (FileWriter wr = new FileWriter(new File(fname))) { for (String s : names) { wr.write(s); wr.write("\n"); } } System.out.printf(" %s: %d names%n", fname, names.length); } // main method to run standalone from jtreg @Test(enabled=false) @Parameters({"x"}) @SuppressWarnings("raw_types") public static void main(@Optional String[] args) { Class<?>[] testclass = { JImageReadTest.class}; TestNG testng = new TestNG(); testng.setTestClasses(testclass); testng.run(); } }