T6838467.java revision 922:6970d9fb8e02
1/* 2 * Copyright (c) 2009, 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 * @bug 6838467 27 * @summary JSR199 FileObjects don't obey general contract of equals. 28 */ 29 30import java.io.*; 31import java.util.*; 32import java.util.zip.*; 33import javax.tools.*; 34import com.sun.tools.javac.file.JavacFileManager; 35import com.sun.tools.javac.main.OptionName; 36import com.sun.tools.javac.util.Context; 37import com.sun.tools.javac.util.Options; 38 39public class T6838467 { 40 boolean fileSystemIsCaseSignificant = !new File("a").equals(new File("A")); 41 42 enum FileKind { 43 DIR("dir"), 44 ZIP("zip"), 45 ZIPFILEINDEX("zip"); 46 FileKind(String path) { 47 file = new File(path); 48 } 49 final File file; 50 }; 51 52 enum CompareKind { 53 SAME { 54 File other(File f) { return f; } 55 }, 56 ABSOLUTE { 57 File other(File f) { return f.getAbsoluteFile(); } 58 }, 59 DIFFERENT { 60 File other(File f) { return new File("not_" + f.getPath()); } 61 }, 62 CASEEQUIV { 63 File other(File f) { return new File(f.getPath().toUpperCase()); } 64 }; 65 abstract File other(File f); 66 }; 67 68 String[] paths = { "p/A.java", "p/B.java", "p/C.java" }; 69 70 public static void main(String... args) throws Exception { 71 new T6838467().run(); 72 } 73 74 void run() throws Exception { 75 // on Windows, verify file system is not case significant 76 if (System.getProperty("os.name").toLowerCase().startsWith("windows") 77 && fileSystemIsCaseSignificant) { 78 error("fileSystemIsCaseSignificant is set on Windows."); 79 } 80 81 // create a set of directories and zip files to compare 82 createTestDir(new File("dir"), paths); 83 createTestDir(new File("not_dir"), paths); 84 createTestZip(new File("zip"), paths); 85 createTestZip(new File("not_zip"), paths); 86 if (fileSystemIsCaseSignificant) { 87 createTestDir(new File("DIR"), paths); 88 createTestZip(new File("ZIP"), paths); 89 } 90 91 // test the various sorts of file objects that can be obtained from 92 // the file manager, and for various values that may or may not match. 93 for (FileKind fk: FileKind.values()) { 94 for (CompareKind ck: CompareKind.values()) { 95 test(fk, ck); 96 } 97 } 98 99 // verify that the various different types of file object were all 100 // tested 101 Set<String> expectClasses = new HashSet<String>(Arrays.asList( 102 "RegularFileObject", "ZipFileObject", "ZipFileIndexFileObject" )); 103 if (!foundClasses.equals(expectClasses)) { 104 error("expected fileobject classes not found\n" 105 + "expected: " + expectClasses + "\n" 106 + "found: " + foundClasses); 107 } 108 109 if (errors > 0) 110 throw new Exception(errors + " errors"); 111 } 112 113 void test(FileKind fk, CompareKind ck) throws IOException { 114 File f1 = fk.file; 115 JavaFileManager fm1 = createFileManager(fk, f1); 116 117 File f2 = ck.other(fk.file); 118 JavaFileManager fm2 = createFileManager(fk, f2); 119 120 try { 121 // If the directories or zip files match, we expect "n" matches in 122 // the "n-squared" comparisons to come, where "n" is the number of 123 // entries in the the directories or zip files. 124 // If the directories or zip files don't themselves match, 125 // we obviously don't expect any of their contents to match either. 126 int expect = (f1.getAbsoluteFile().equals(f2.getAbsoluteFile()) ? paths.length : 0); 127 128 System.err.println("test " + (++count) + " " + fk + " " + ck + " " + f1 + " " + f2); 129 test(fm1, fm2, expect); 130 131 } finally { 132 fm1.close(); 133 fm2.close(); 134 } 135 } 136 137 // For a pair of file managers that may or may not have similar entries 138 // on the classpath, compare all files returned from one against all files 139 // returned from the other. For each pair of files, verify that if they 140 // are equal, the hashcode is equal as well, and finally verify that the 141 // expected number of matches was found. 142 void test(JavaFileManager fm1, JavaFileManager fm2, int expectEqualCount) throws IOException { 143 boolean foundFiles1 = false; 144 boolean foundFiles2 = false; 145 int foundEqualCount = 0; 146 Set<JavaFileObject.Kind> kinds = EnumSet.allOf(JavaFileObject.Kind.class); 147 for (FileObject fo1: fm1.list(StandardLocation.CLASS_PATH, "p", kinds, false)) { 148 foundFiles1 = true; 149 foundClasses.add(fo1.getClass().getSimpleName()); 150 for (FileObject fo2: fm2.list(StandardLocation.CLASS_PATH, "p", kinds, false)) { 151 foundFiles2 = true; 152 foundClasses.add(fo1.getClass().getSimpleName()); 153 System.err.println("compare " + fo1 + " " + fo2); 154 if (fo1.equals(fo2)) { 155 foundEqualCount++; 156 int hash1 = fo1.hashCode(); 157 int hash2 = fo2.hashCode(); 158 if (hash1 != hash2) 159 error("hashCode error: " + fo1 + " [" + hash1 + "] " 160 + fo2 + " [" + hash2 + "]"); 161 } 162 } 163 } 164 if (!foundFiles1) 165 error("no files found for file manager 1"); 166 if (!foundFiles2) 167 error("no files found for file manager 2"); 168 // verify the expected number of matches were found 169 if (foundEqualCount != expectEqualCount) 170 error("expected matches not found: expected " + expectEqualCount + ", found " + foundEqualCount); 171 } 172 173 // create a file manager to test a FileKind, with a given directory 174 // or zip file placed on the classpath 175 JavaFileManager createFileManager(FileKind fk, File classpath) throws IOException { 176 StandardJavaFileManager fm = createFileManager(fk == FileKind.ZIP); 177 fm.setLocation(StandardLocation.CLASS_PATH, Arrays.asList(classpath)); 178 return fm; 179 } 180 181 JavacFileManager createFileManager(boolean useOptimizedZip) { 182 Context ctx = new Context(); 183 Options options = Options.instance(ctx); 184 options.put("useOptimizedZip", Boolean.toString(useOptimizedZip)); 185 return new JavacFileManager(ctx, false, null); 186 } 187 188 // create a directory containing a given set of paths 189 void createTestDir(File dir, String[] paths) throws IOException { 190 for (String p: paths) { 191 File file = new File(dir, p); 192 file.getParentFile().mkdirs(); 193 FileWriter out = new FileWriter(file); 194 try { 195 out.write(p); 196 } finally { 197 out.close(); 198 } 199 } 200 } 201 202 // create a sip file containing a given set of entries 203 void createTestZip(File zip, String[] paths) throws IOException { 204 if (zip.getParentFile() != null) 205 zip.getParentFile().mkdirs(); 206 ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip)); 207 try { 208 for (String p: paths) { 209 ZipEntry ze = new ZipEntry(p); 210 zos.putNextEntry(ze); 211 byte[] bytes = p.getBytes(); 212 zos.write(bytes, 0, bytes.length); 213 zos.closeEntry(); 214 } 215 } finally { 216 zos.close(); 217 } 218 } 219 220 void error(String msg) { 221 System.err.println("Error: " + msg); 222 errors++; 223 } 224 225 int count; 226 int errors; 227 Set<String> foundClasses = new HashSet<String>(); 228} 229 230