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 }
--- EOF ---