1 /* 2 * Copyright (c) 2010, 2011, 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 module file hashing. 27 */ 28 29 import java.io.*; 30 import java.security.*; 31 import java.util.*; 32 import org.openjdk.jigsaw.*; 33 import org.openjdk.jigsaw.cli.*; 34 35 public class ModuleFormatHeaderHashTest { 36 final String MNAME = "hello"; 37 final String MVER = "0.1"; 38 String moduleinfo = "module " + MNAME + " @ " + MVER + " {}"; 39 40 public static void main(String[] args) throws Exception { 41 new ModuleFormatHeaderHashTest().run(); 42 } 43 44 void run() throws Exception { 45 try { 46 test(); 47 } catch (Throwable t) { 48 t.printStackTrace(); 49 errors++; 50 } 51 52 53 if (errors == 0) 54 System.out.println(count + " tests passed"); 55 else 56 throw new Exception(errors + "/" + count + " tests failed"); 57 } 58 59 void testEmptyModule() throws Exception { 60 System.err.println("Test: Empty module"); 61 count++; 62 reset(); 63 List<File> files = new ArrayList<File>(); 64 addFile(files, createFile("module-info.java", moduleinfo)); 65 compile(files); 66 compress(MNAME); 67 byte [] expected = readHash(MNAME, MVER); 68 byte [] computed = hash(MNAME, MVER, "SHA-256"); 69 if (!MessageDigest.isEqual(expected, computed)) 70 throw new IOException("Expected and computed file hashes don't match"); 71 } 72 73 void test() throws Exception { 74 testEmptyModule(); 75 } 76 77 /** 78 * Get a module file's stored hash. 79 */ 80 byte [] readHash(String name, String version) throws Exception { 81 String fname = moduleDir + File.separator + name + "@" + version + ".jmod"; 82 try (FileInputStream fis = new FileInputStream(fname); 83 DataInputStream in = new DataInputStream(fis); 84 ModuleFile.Reader r = new ModuleFile.Reader(in);) { 85 return r.getHash(); 86 } 87 } 88 89 /** 90 * Hash a module file (without the file hash in the module file header). 91 */ 92 static final int LENGTH_WITHOUT_HASH = 30; // computed from module-file format 93 byte [] hash(String name, String version, String digest) throws Exception { 94 String fname = moduleDir + File.separator + name + "@" + version + ".jmod"; 95 MessageDigest md = MessageDigest.getInstance(digest); 96 try (FileInputStream fis = new FileInputStream(fname); 97 DigestInputStream dis = new DigestInputStream(fis, md)) { 98 dis.read(new byte[LENGTH_WITHOUT_HASH]); 99 dis.on(false); 100 dis.read(new byte [md.getDigestLength()]); 101 dis.on(true); 102 for (int c = dis.read() ; c != -1 ; c = dis.read()) 103 ; 104 return md.digest(); 105 } 106 } 107 108 /** 109 * Compress a module. 110 */ 111 void compress(String name) throws Exception { 112 compress(name, false); 113 } 114 115 void compress(String name, boolean haveNatLibs) 116 throws Exception { 117 compress(name, haveNatLibs, false); 118 } 119 120 void compress(String name, boolean haveNatLibs, 121 boolean haveNatCmds) throws Exception { 122 compress(name, haveNatLibs, haveNatCmds, false); 123 } 124 125 void compress(String name, boolean haveNatLibs, 126 boolean haveNatCmds, boolean haveConfig) 127 throws Exception { 128 List<String> args = new ArrayList<String>(); 129 args.add("-m"); 130 args.add(classesDir.getAbsolutePath()); 131 args.add("-d"); 132 args.add(moduleDir.getAbsolutePath()); 133 if (haveNatLibs) { 134 args.add("--natlib"); 135 args.add(natlibDir.toString()); 136 } 137 if (haveNatCmds) { 138 args.add("--natcmd"); 139 args.add(natcmdDir.toString()); 140 } 141 if (haveConfig) { 142 args.add("--config"); 143 args.add(configDir.toString()); 144 } 145 args.add("jmod"); 146 args.add("hello"); 147 Packager.main(args.toArray(new String[0])); 148 } 149 150 /** 151 * Compile a list of files. 152 */ 153 void compile(List<File> files) { 154 List<String> options = new ArrayList<String>(); 155 options.addAll(Arrays.asList("-source", "8", "-d", classesDir.getPath())); 156 for (File f: files) 157 options.add(f.getPath()); 158 159 String[] opts = options.toArray(new String[options.size()]); 160 StringWriter sw = new StringWriter(); 161 try (PrintWriter pw = new PrintWriter(sw)) { 162 int rc = com.sun.tools.javac.Main.compile(opts, pw); 163 164 String out = sw.toString(); 165 if (out.trim().length() > 0) 166 System.err.println(out); 167 if (rc != 0) 168 throw new Error("compilation failed: rc=" + rc); 169 } 170 } 171 172 /** 173 * Add a file to a list if the file is not null. 174 */ 175 void addFile(List<File> files, File file) { 176 if (file != null) 177 files.add(file); 178 } 179 180 181 /** 182 * Create a test file with given content if the content is not null. 183 */ 184 File createFile(String path, String body) throws IOException { 185 if (body == null) 186 return null; 187 File file = new File(srcDir, path); 188 file.getAbsoluteFile().getParentFile().mkdirs(); 189 try (FileWriter out = new FileWriter(file)) { 190 out.write(body); 191 } 192 return file; 193 } 194 195 /** 196 * Set up empty src and classes directories for a test. 197 */ 198 void reset() { 199 resetDir(srcDir); 200 resetDir(classesDir); 201 resetDir(moduleDir); 202 resetDir(new File(MNAME)); 203 } 204 205 /** 206 * Set up an empty directory. 207 */ 208 void resetDir(File dir) { 209 if (dir.exists()) 210 deleteAll(dir); 211 dir.mkdirs(); 212 } 213 214 /** 215 * Delete a file or a directory (including all its contents). 216 */ 217 boolean deleteAll(File file) { 218 if (file.isDirectory()) { 219 for (File f: file.listFiles()) 220 deleteAll(f); 221 } 222 return file.delete(); 223 } 224 225 /** 226 * Report an error. 227 */ 228 void error(String msg, String... more) { 229 System.err.println("error: " + msg); 230 for (String s: more) 231 System.err.println(s); 232 errors++; 233 } 234 235 int count; 236 int errors; 237 File srcDir = new File("tmp", "src"); // use "tmp" to help avoid accidents 238 File classesDir = new File("tmp", "classes"); 239 File moduleDir = new File("tmp", "modules"); 240 File natlibDir = new File(srcDir, "natlib"); 241 File natcmdDir = new File(srcDir, "natcmd"); 242 File configDir = new File(srcDir, "config"); 243 } --- EOF ---