PageRenderTime 27ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/netbeans-7.3/o.n.core/test/qa-functional/src/org/netbeans/core/validation/BytecodeTest.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 437 lines | 326 code | 48 blank | 63 comment | 89 complexity | 6e0ee417454b7600591fe4f6aec115a3 MD5 | raw file
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  5. *
  6. * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  7. * Other names may be trademarks of their respective owners.
  8. *
  9. * The contents of this file are subject to the terms of either the GNU
  10. * General Public License Version 2 only ("GPL") or the Common
  11. * Development and Distribution License("CDDL") (collectively, the
  12. * "License"). You may not use this file except in compliance with the
  13. * License. You can obtain a copy of the License at
  14. * http://www.netbeans.org/cddl-gplv2.html
  15. * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  16. * specific language governing permissions and limitations under the
  17. * License. When distributing the software, include this License Header
  18. * Notice in each file and include the License file at
  19. * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
  20. * particular file as subject to the "Classpath" exception as provided
  21. * by Oracle in the GPL Version 2 section of the License file that
  22. * accompanied this code. If applicable, add the following below the
  23. * License Header, with the fields enclosed by brackets [] replaced by
  24. * your own identifying information:
  25. * "Portions Copyrighted [year] [name of copyright owner]"
  26. *
  27. * Contributor(s):
  28. *
  29. * The Original Software is NetBeans. The Initial Developer of the Original
  30. * Software is Sun Microsystems, Inc. Portions Copyright 2006 Sun
  31. * Microsystems, Inc. All Rights Reserved.
  32. *
  33. * If you wish your version of this file to be governed by only the CDDL
  34. * or only the GPL Version 2, indicate your decision by adding
  35. * "[Contributor] elects to include this software in this distribution
  36. * under the [CDDL or GPL Version 2] license." If you do not indicate a
  37. * single choice of license, a recipient has the option to distribute
  38. * your version of this file under either the CDDL, the GPL Version 2 or
  39. * to extend the choice of license to its licensees as provided above.
  40. * However, if you add GPL Version 2 code and therefore, elected the GPL
  41. * Version 2 license, then the option applies only if the new code is
  42. * made subject to such option by the copyright holder.
  43. */
  44. // XXX rewrite to NbModuleSuite
  45. package org.netbeans.core.validation;
  46. import java.io.File;
  47. import java.util.Enumeration;
  48. import java.util.Set;
  49. import java.util.jar.JarEntry;
  50. import java.util.jar.JarFile;
  51. import com.sun.org.apache.bcel.internal.classfile.ClassParser;
  52. import com.sun.org.apache.bcel.internal.classfile.DescendingVisitor;
  53. import com.sun.org.apache.bcel.internal.classfile.EmptyVisitor;
  54. import com.sun.org.apache.bcel.internal.classfile.Field;
  55. import com.sun.org.apache.bcel.internal.classfile.JavaClass;
  56. import com.sun.org.apache.bcel.internal.classfile.LineNumberTable;
  57. import com.sun.org.apache.bcel.internal.classfile.LocalVariableTable;
  58. import com.sun.org.apache.bcel.internal.classfile.Method;
  59. import com.sun.org.apache.bcel.internal.generic.Type;
  60. import java.lang.reflect.Constructor;
  61. import java.util.LinkedList;
  62. import java.util.List;
  63. import java.util.Map;
  64. import java.util.SortedMap;
  65. import java.util.TreeMap;
  66. import java.util.TreeSet;
  67. import java.util.logging.Level;
  68. import java.util.logging.Logger;
  69. import org.netbeans.junit.NbTestCase;
  70. import org.openide.loaders.DataLoader;
  71. import org.openide.loaders.DataLoaderPool;
  72. /**
  73. *
  74. * @author radim
  75. */
  76. public class BytecodeTest extends NbTestCase {
  77. private Logger LOG;
  78. public BytecodeTest(String testName) {
  79. super(testName);
  80. }
  81. @Override
  82. protected Level logLevel() {
  83. return Level.INFO;
  84. }
  85. protected void setUp() throws Exception {
  86. LOG = Logger.getLogger("TEST-" + getName());
  87. super.setUp();
  88. }
  89. // TODO test for ModuleInstall subclasses - they should override at least one important method
  90. private static class Violation implements Comparable<Violation> {
  91. String entry;
  92. String jarFile;
  93. String comment;
  94. Violation(String entry, String jarFile, String comment) {
  95. this.entry = entry;
  96. this.jarFile = jarFile;
  97. this.comment = comment;
  98. }
  99. public int compareTo(Violation v2) {
  100. String second = v2.entry + v2.jarFile;
  101. return (entry +jarFile).compareTo(second);
  102. }
  103. }
  104. private static class MyVisitor extends EmptyVisitor {
  105. private boolean localVarTable;
  106. private boolean lineNumberTable;
  107. public void visitLocalVariableTable(LocalVariableTable obj) {
  108. localVarTable = true;
  109. }
  110. public boolean foundLocalVarTable() {
  111. return localVarTable;
  112. }
  113. public void visitLineNumberTable(LineNumberTable obj) {
  114. lineNumberTable = true;
  115. }
  116. public boolean foundLineNumberTable() {
  117. return lineNumberTable;
  118. }
  119. }
  120. private static class BIVisitor extends EmptyVisitor {
  121. private static Type pdType = Type.getType("[Ljava/beans/PropertyDescriptor;");
  122. private static Type bdType = Type.getType("Ljava/beans/BeanDescriptor;");
  123. private static Type mdType = Type.getType("[Ljava/beans/MethodDescriptor;");
  124. private static Type edType = Type.getType("[Ljava/beans/EventSetDescriptor;");
  125. private boolean hasDescFields;
  126. private boolean hasStaticMethods;
  127. public void visitField(Field obj) {
  128. if (obj.isStatic()) {
  129. // System.out.println("signature "+obj.getSignature());
  130. Type name = Type.getReturnType(obj.getSignature());
  131. if (pdType.equals(name) ||
  132. bdType.equals(name) ||
  133. mdType.equals(name) ||
  134. edType.equals(name)) {
  135. hasDescFields = true;
  136. }
  137. }
  138. }
  139. public void visitMethod(Method obj) {
  140. if (obj.isStatic()) { // && obj.getArgumentTypes().length == 0) {
  141. String name = obj.getName();
  142. if ("getBdescriptor".equals(name) ||
  143. "getMdescriptor".equals(name) ||
  144. "getEdescriptor".equals(name) ||
  145. "getPdescriptor".equals(name)) {
  146. hasStaticMethods = true;
  147. }
  148. }
  149. }
  150. public boolean foundDescFields() {
  151. return hasDescFields;
  152. }
  153. public boolean foundStaticMethods() {
  154. return hasStaticMethods;
  155. }
  156. }
  157. private static class StaticsVisitor extends EmptyVisitor {
  158. private static Type imageType = Type.getType("Ljava/awt/Image;");
  159. private static Type image1Type = Type.getType("Ljavax/swing/ImageIcon;");
  160. private static Type image2Type = Type.getType("Ljavax/swing/Icon;");
  161. private static Type bType = Type.getType("Ljava/util/ResourceBundle;");
  162. private static Type b2Type = Type.getType("Lorg/openide/util/NbBundle;");
  163. private boolean hasImageFields;
  164. private boolean hasPropFields;
  165. @Override public void visitField(Field obj) {
  166. if (obj.isStatic()) {
  167. // System.out.println("signature "+obj.getSignature());
  168. Type name = Type.getReturnType(obj.getSignature());
  169. if (imageType.equals(name) ||
  170. image1Type.equals(name) ||
  171. image2Type.equals(name)) {
  172. hasImageFields = true;
  173. }
  174. if (bType.equals(name) ||
  175. b2Type.equals(name)) {
  176. hasPropFields = true;
  177. }
  178. }
  179. }
  180. public boolean foundStaticFields() {
  181. return hasImageFields | hasPropFields;
  182. }
  183. public String fieldTypes() {
  184. if (hasImageFields) {
  185. return hasPropFields? "images and bundle resources": "images";
  186. }
  187. else {
  188. return hasPropFields? "bundle resources": "none";
  189. }
  190. }
  191. }
  192. /** Scan of BeanInfo classes to check if they held descriptors statically
  193. */
  194. public void testBeanInfos() throws Exception {
  195. JavaClass clz;
  196. Set<Violation> violations = new TreeSet<Violation>();
  197. for (File f: org.netbeans.core.startup.Main.getModuleSystem().getModuleJars()) {
  198. if (!f.getName().endsWith(".jar"))
  199. continue;
  200. JarFile jar = new JarFile(f);
  201. Enumeration<JarEntry> entries = jar.entries();
  202. JarEntry entry;
  203. while (entries.hasMoreElements()) {
  204. entry = entries.nextElement();
  205. if (entry.getName().endsWith("BeanInfo.class")) {
  206. LOG.log(Level.FINE, "testing entry {0}", entry);
  207. if (entry.getName().endsWith("JXPathBasicBeanInfo.class")) {
  208. continue;
  209. }
  210. clz = new ClassParser(jar.getInputStream(entry), entry.getName()).parse();
  211. assertNotNull("classfile of "+entry.toString()+" parsed");
  212. BIVisitor v = new BIVisitor();
  213. new DescendingVisitor(clz,v).visit();
  214. if (v.foundDescFields()) {
  215. violations.add(new Violation(entry.toString(), jar.getName(), " found fields that should be avoided"));
  216. }
  217. if (v.foundStaticMethods()) {
  218. violations.add(new Violation(entry.toString(), jar.getName(), " found methods that should be avoided"));
  219. }
  220. }
  221. }
  222. }
  223. if (!violations.isEmpty()) {
  224. StringBuilder msg = new StringBuilder();
  225. msg.append("Some BeanInfo classes should be more optimized:\n");
  226. for (Violation v: violations) {
  227. msg.append(v.entry).append(" in ").append(v.jarFile).append(v.comment).append('\n');
  228. }
  229. fail(msg.toString());
  230. }
  231. }
  232. /** Scan of all classes to check if they held statically things like Images or ResourceBundles
  233. */
  234. public void testStaticRefs() throws Exception {
  235. JavaClass clz;
  236. // TODO need to exclude some usages that are justified
  237. Set<Violation> violations = new TreeSet<Violation>();
  238. for (File f: org.netbeans.core.startup.Main.getModuleSystem().getModuleJars()) {
  239. if (!f.getName().endsWith(".jar"))
  240. continue;
  241. if (f.getName().endsWith("servlet-2.2.jar")
  242. || f.getName().endsWith("servlet3.0-jsp2.2-api.jar")
  243. || f.getName().endsWith("javaee.jar")
  244. || f.getName().endsWith("javac-impl-nb-7.0-b07.jar")
  245. || f.getName().endsWith("jaxb-impl.jar")
  246. || f.getName().endsWith("jaxb-xjc.jar")
  247. || f.getName().endsWith("saaj-impl.jar")
  248. || f.getName().endsWith("jh-2.0_05.jar")
  249. || f.getName().endsWith("xerces-2.8.0.jar")
  250. || f.getName().endsWith("svnClientAdapter.jar")
  251. || f.getName().endsWith("beansbinding-0.5.jar")
  252. || f.getName().endsWith("persistence-tool-support.jar") // issue #96439
  253. || f.getName().endsWith("org-netbeans-modules-websvc-core.jar") // issue #96453
  254. || f.getName().endsWith("org-netbeans-modules-websvc-jaxrpc.jar")
  255. || f.getName().endsWith("org-netbeans-modules-websvc-design.jar") // issue #99971
  256. || f.getName().endsWith("org-netbeans-modules-j2ee-sun-appsrv.jar") // issue #96439
  257. || f.getName().endsWith("org-netbeans-modules-j2ee-sun-appsrv81.jar")
  258. || f.getName().endsWith("org-netbeans-modules-j2ee-ejbjarproject.jar") // issue #96423
  259. || f.getName().endsWith("org-netbeans-modules-j2ee-earproject.jar")
  260. || f.getName().endsWith("org-netbeans-modules-j2ee-clientproject.jar")
  261. || f.getName().endsWith("org-netbeans-modules-j2ee-blueprints.jar")
  262. || f.getName().endsWith("org-netbeans-modules-j2ee-archive.jar")
  263. || f.getName().endsWith("org-netbeans-modules-j2ee-ddloaders.jar")
  264. || f.getName().endsWith("org-netbeans-modules-j2ee-dd.jar")
  265. || f.getName().endsWith("org-netbeans-modules-j2ee-api-ejbmodule.jar")
  266. || f.getName().endsWith("org-netbeans-modules-web-project.jar") // issue #96427
  267. || f.getName().endsWith("org-netbeans-modules-web-core-syntax.jar")
  268. || f.getName().endsWith("org-netbeans-modules-java-source.jar") // issue #96461
  269. || f.getName().endsWith("org-netbeans-modules-java-project.jar")
  270. || f.getName().endsWith("org-netbeans-modules-java-j2seproject.jar")
  271. || f.getName().endsWith("org-netbeans-modules-java-platform.jar")
  272. || f.getName().endsWith("org-netbeans-modules-j2ee-sun-ddui.jar")) { // issue #96422
  273. continue;
  274. }
  275. // #97283 - profiler
  276. if (f.getName().contains("jfluid")
  277. || f.getName().contains("profiler")
  278. ) {
  279. continue;
  280. }
  281. JarFile jar = new JarFile(f);
  282. Enumeration<JarEntry> entries = jar.entries();
  283. JarEntry entry;
  284. while (entries.hasMoreElements()) {
  285. entry = entries.nextElement();
  286. if (entry.getName().endsWith(".class")) {
  287. if ("org/openide/explorer/view/VisualizerNode.class".equals(entry.getName()) // default node icon si OK
  288. || "org/openide/awt/JInlineMenu.class".equals(entry.getName()) // empty icon si OK
  289. || "org/openide/awt/DynaMenuModel.class".equals(entry.getName()) // empty icon si OK
  290. || "org/netbeans/swing/tabcontrol/TabData.class".equals(entry.getName()) // empty icon si OK
  291. || "org/openide/explorer/propertysheet/PropertySheet.class".equals(entry.getName())) { // deprecated kept for compat
  292. continue;
  293. } else if (entry.getName().startsWith("org/netbeans/modules/editor/java/JavaCompletionItem") // #96442
  294. // || entry.getName().startsWith("org/netbeans/api/visual") // 99964
  295. ) {
  296. continue;
  297. }
  298. LOG.log(Level.FINE, "testing entry {0}", entry);
  299. clz = new ClassParser(jar.getInputStream(entry), entry.getName()).parse();
  300. assertNotNull("classfile of "+entry.toString()+" parsed");
  301. StaticsVisitor v = new StaticsVisitor();
  302. new DescendingVisitor(clz,v).visit();
  303. if (v.foundStaticFields()) {
  304. violations.add(new Violation(entry.toString(), jar.getName(), " has static fields of type "+v.fieldTypes()));
  305. }
  306. }
  307. }
  308. }
  309. if (!violations.isEmpty()) {
  310. StringBuilder msg = new StringBuilder();
  311. msg.append("Some classes retain memory permanently (").append(violations.size()).append("):\n");
  312. for (Violation v: violations) {
  313. msg.append(v.entry).append(v.comment).append(" (").append(v.jarFile).append(")\n");
  314. }
  315. fail(msg.toString());
  316. }
  317. }
  318. /** Check that we are not loading classes hungrily.
  319. * DataLoader(String) is prefered to avoid loading of DataObject classes.
  320. */
  321. public void testDataLoaders() throws Exception {
  322. Enumeration<DataLoader> loaders = DataLoaderPool.getDefault().allLoaders();
  323. while (loaders.hasMoreElements()) {
  324. DataLoader ldr = loaders.nextElement();
  325. if ("org.netbeans.modules.cnd.loaders.CCDataLoader".equals(ldr.getClass().getName())) { // #97612
  326. continue;
  327. }
  328. try {
  329. // XXX not enough better is to test that all ctors only call super(String)
  330. Constructor ctor = ldr.getClass().getDeclaredConstructor(Class.class);
  331. assertNull(ldr.getClass().getName()+".<init>(String) is better are usualy enough", ctor);
  332. } catch (NoSuchMethodException ex) {
  333. // expected path - OK
  334. }
  335. }
  336. }
  337. public void testDuplicateClasses() throws Exception {
  338. SortedMap<String, List<String>> res2jars = new TreeMap<String, List<String>>();
  339. Set<Violation> violations = new TreeSet<Violation>();
  340. for (File f: org.netbeans.core.startup.Main.getModuleSystem().getModuleJars()) {
  341. if (!f.getName().endsWith(".jar"))
  342. continue;
  343. if (f.getName().endsWith("servlet-2.2.jar")
  344. || f.getName().endsWith("servlet3.0-jsp2.2-api.jar")
  345. || f.getName().endsWith("cdc-pp-awt-layout.jar")) // #105314
  346. continue;
  347. if (f.getName().endsWith("tsalljlayoutclient601dev.jar") // #105628
  348. || f.getName().endsWith("tsalljlayoutserver601dev.jar") // #105628
  349. || f.getName().endsWith("lucene-core-2.1.0.jar") // #105329
  350. || f.getName().endsWith("batik-mod.jar") // #100892
  351. || f.getName().endsWith("batik-all.jar") // #100892
  352. || f.getName().endsWith("JGo5.1.jar") // #105319
  353. || f.getName().endsWith("JGoLayout5.1.jar") // #105319
  354. || f.getName().endsWith("JGoInstruments5.1.jar")) // #105319
  355. continue;
  356. JarFile jar = new JarFile(f);
  357. Enumeration<JarEntry> entries = jar.entries();
  358. JarEntry entry;
  359. while (entries.hasMoreElements()) {
  360. entry = entries.nextElement();
  361. String name = entry.getName();
  362. if (!name.endsWith(".class"))
  363. continue;
  364. LOG.log(Level.FINE, "testing entry {0}", entry);
  365. List<String> jars = res2jars.get(name);
  366. if (jars == null) {
  367. jars = new LinkedList<String>();
  368. res2jars.put(name, jars);
  369. }
  370. if (!jars.contains(jar.getName())) { // avoid errors for multiply loaded JARs
  371. jars.add(jar.getName());
  372. }
  373. }
  374. }
  375. boolean fail = false;
  376. StringBuilder msg = new StringBuilder("There are some duplicated classes in IDE\n");
  377. for (Map.Entry<String, List<String>> entry: res2jars.entrySet()) {
  378. if (entry.getValue().size() > 1) {
  379. fail = true;
  380. msg.append(entry.getKey()).append(" is contained in ").
  381. append(entry.getValue().size()).append(" files: ").
  382. append(entry.getValue().toString()).append('\n');
  383. }
  384. }
  385. if (fail) {
  386. fail(msg.toString());
  387. }
  388. }
  389. }