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 byte [] hash(String name, String version, String digest) throws Exception { 93 String fname = moduleDir + File.separator + name + "@" + version + ".jmod"; 94 MessageDigest md = MessageDigest.getInstance(digest); 95 try (FileInputStream fis = new FileInputStream(fname); 96 DigestInputStream dis = new DigestInputStream(fis, md)) { 97 dis.read(new byte[ModuleFile.ModuleFileHeader.LENGTH_WITHOUT_HASH]); 98 dis.on(false); 99 dis.read(new byte [md.getDigestLength()]); 100 dis.on(true); 101 for (int c = dis.read() ; c != -1 ; c = dis.read()) 102 ; 103 return md.digest(); 104 } 105 } 106 107 /** 108 * Compress a module. 109 */ 110 void compress(String name) throws Exception { 111 compress(name, false); 112 } 113 114 void compress(String name, boolean haveNatLibs) 115 throws Exception { 116 compress(name, haveNatLibs, false); 117 } 118 119 void compress(String name, boolean haveNatLibs, 120 boolean haveNatCmds) throws Exception { 121 compress(name, haveNatLibs, haveNatCmds, false); 122 } 123 124 void compress(String name, boolean haveNatLibs, 125 boolean haveNatCmds, boolean haveConfig) 126 throws Exception { 127 List<String> args = new ArrayList<String>(); 128 args.add("-m"); 129 args.add(classesDir.getAbsolutePath()); 130 args.add("-d"); 131 args.add(moduleDir.getAbsolutePath()); 132 if (haveNatLibs) { 133 args.add("--natlib"); 134 args.add(natlibDir.toString()); 135 } 136 if (haveNatCmds) { 137 args.add("--natcmd"); 138 args.add(natcmdDir.toString()); 139 } 140 if (haveConfig) { 141 args.add("--config"); 142 args.add(configDir.toString()); 143 } 144 args.add("jmod"); 145 args.add("hello"); 146 Packager.main(args.toArray(new String[0])); 147 } 148 149 /** 150 * Compile a list of files. 151 */ 152 void compile(List<File> files) { 153 List<String> options = new ArrayList<String>(); 154 options.addAll(Arrays.asList("-source", "8", "-d", classesDir.getPath())); 155 for (File f: files) 156 options.add(f.getPath()); 157 158 String[] opts = options.toArray(new String[options.size()]); 159 StringWriter sw = new StringWriter(); 160 try (PrintWriter pw = new PrintWriter(sw)) { 161 int rc = com.sun.tools.javac.Main.compile(opts, pw); 162 163 String out = sw.toString(); 164 if (out.trim().length() > 0) 165 System.err.println(out); 166 if (rc != 0) 167 throw new Error("compilation failed: rc=" + rc); 168 } 169 } 170 171 /** 172 * Add a file to a list if the file is not null. 173 */ 174 void addFile(List<File> files, File file) { 175 if (file != null) 176 files.add(file); 177 } 178 179 180 /** 181 * Create a test file with given content if the content is not null. 182 */ 183 File createFile(String path, String body) throws IOException { 184 if (body == null) 185 return null; 186 File file = new File(srcDir, path); 187 file.getAbsoluteFile().getParentFile().mkdirs(); 188 try (FileWriter out = new FileWriter(file)) { 189 out.write(body); 190 } 191 return file; 192 } 193 194 /** 195 * Set up empty src and classes directories for a test. 196 */ 197 void reset() { 198 resetDir(srcDir); 199 resetDir(classesDir); 200 resetDir(moduleDir); 201 resetDir(new File(MNAME)); 202 } 203 204 /** 205 * Set up an empty directory. 206 */ 207 void resetDir(File dir) { 208 if (dir.exists()) 209 deleteAll(dir); 210 dir.mkdirs(); 211 } 212 213 /** 214 * Delete a file or a directory (including all its contents). 215 */ 216 boolean deleteAll(File file) { 217 if (file.isDirectory()) { 218 for (File f: file.listFiles()) 219 deleteAll(f); 220 } 221 return file.delete(); 222 } 223 224 /** 225 * Report an error. 226 */ 227 void error(String msg, String... more) { 228 System.err.println("error: " + msg); 229 for (String s: more) 230 System.err.println(s); 231 errors++; 232 } 233 234 int count; 235 int errors; 236 File srcDir = new File("tmp", "src"); // use "tmp" to help avoid accidents 237 File classesDir = new File("tmp", "classes"); 238 File moduleDir = new File("tmp", "modules"); 239 File natlibDir = new File(srcDir, "natlib"); 240 File natcmdDir = new File(srcDir, "natcmd"); 241 File configDir = new File(srcDir, "config"); 242 }