Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

TestBench.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. package com.vaadin.tests;
  2. import java.io.File;
  3. import java.net.URL;
  4. import java.util.ArrayList;
  5. import java.util.Enumeration;
  6. import java.util.HashSet;
  7. import java.util.List;
  8. import java.util.Locale;
  9. import java.util.Set;
  10. import com.vaadin.server.ExternalResource;
  11. import com.vaadin.server.LegacyApplication;
  12. import com.vaadin.ui.Component;
  13. import com.vaadin.ui.CustomComponent;
  14. import com.vaadin.ui.HorizontalSplitPanel;
  15. import com.vaadin.ui.Label;
  16. import com.vaadin.ui.Layout;
  17. import com.vaadin.ui.LegacyWindow;
  18. import com.vaadin.ui.Link;
  19. import com.vaadin.ui.Panel;
  20. import com.vaadin.ui.VerticalLayout;
  21. import com.vaadin.v7.data.Property;
  22. import com.vaadin.v7.data.util.HierarchicalContainer;
  23. import com.vaadin.v7.ui.Tree;
  24. /**
  25. * TestBench finds out testable classes within given java packages and adds them
  26. * to menu from where they can be executed. Class is considered testable if it
  27. * is of class Application or CustomComponent.
  28. *
  29. * Note: edit TestBench.testablePackages array
  30. *
  31. * @author Vaadin Ltd.
  32. *
  33. */
  34. public class TestBench extends com.vaadin.server.LegacyApplication
  35. implements Property.ValueChangeListener {
  36. // Add here packages which are used for finding testable classes
  37. String[] testablePackages = { "com.vaadin.tests",
  38. "com.vaadin.tests.tickets" };
  39. HierarchicalContainer testables = new HierarchicalContainer();
  40. LegacyWindow mainWindow = new LegacyWindow("TestBench window");
  41. // Main layout consists of tree menu and body layout
  42. HorizontalSplitPanel mainLayout = new HorizontalSplitPanel();
  43. Tree menu;
  44. VerticalLayout bodyLayout = new VerticalLayout();
  45. Set<Class<?>> itemCaptions = new HashSet<>();
  46. @Override
  47. public void init() {
  48. // Add testable classes to hierarchical container
  49. for (int p = 0; p < testablePackages.length; p++) {
  50. testables.addItem(testablePackages[p]);
  51. try {
  52. final List<Class<?>> testableClasses = getTestableClassesForPackage(
  53. testablePackages[p]);
  54. for (final Class<?> t : testableClasses) {
  55. // ignore TestBench itself
  56. if (t.equals(TestBench.class)) {
  57. continue;
  58. }
  59. try {
  60. testables.addItem(t);
  61. itemCaptions.add(t);
  62. testables.setParent(t, testablePackages[p]);
  63. testables.setChildrenAllowed(t, false);
  64. continue;
  65. } catch (final Exception e) {
  66. try {
  67. testables.addItem(t);
  68. itemCaptions.add(t);
  69. testables.setParent(t, testablePackages[p]);
  70. testables.setChildrenAllowed(t, false);
  71. continue;
  72. } catch (final Exception e1) {
  73. e1.printStackTrace();
  74. }
  75. }
  76. }
  77. } catch (final Exception e) {
  78. e.printStackTrace();
  79. }
  80. }
  81. menu = new Tree("Testables", testables);
  82. for (final Class<?> testable : itemCaptions) {
  83. // simplify captions
  84. final String name = testable.getName()
  85. .substring(testable.getName().lastIndexOf('.') + 1);
  86. menu.setItemCaption(testable, name);
  87. }
  88. // expand all root items
  89. for (final Object id : menu.rootItemIds()) {
  90. menu.expandItemsRecursively(id);
  91. }
  92. menu.addListener(this);
  93. menu.setImmediate(true);
  94. menu.setNullSelectionAllowed(false);
  95. VerticalLayout lo = new VerticalLayout();
  96. lo.addComponent(menu);
  97. mainWindow.getPage().addUriFragmentChangedListener(event -> {
  98. String fragment = event.getUriFragment();
  99. if (fragment != null && !fragment.isEmpty()) {
  100. // try to find a proper test class
  101. // exact match
  102. for (Object next : menu.getItemIds()) {
  103. if (next instanceof Class) {
  104. Class<?> c = (Class<?>) next;
  105. String string = c.getName();
  106. if (string.equals(fragment)) {
  107. menu.setValue(c);
  108. mainLayout.setSplitPosition(0);
  109. return;
  110. }
  111. }
  112. }
  113. // simple name match
  114. for (Object next : menu.getItemIds()) {
  115. if (next instanceof Class) {
  116. Class<?> c = (Class<?>) next;
  117. String string = c.getSimpleName();
  118. if (string.equals(fragment)) {
  119. menu.setValue(c);
  120. mainLayout.setSplitPosition(0);
  121. return;
  122. }
  123. }
  124. }
  125. // ticket match
  126. for (Object next : menu.getItemIds()) {
  127. if (next instanceof Class) {
  128. Class<?> c = (Class<?>) next;
  129. String string = c.getSimpleName();
  130. if (string.startsWith("Ticket" + fragment)) {
  131. menu.setValue(c);
  132. mainLayout.setSplitPosition(0);
  133. return;
  134. }
  135. }
  136. }
  137. // just partly match lowercase
  138. for (Object next : menu.getItemIds()) {
  139. if (next instanceof Class) {
  140. Class<?> c = (Class<?>) next;
  141. String string = c.getSimpleName();
  142. if (string.toLowerCase(Locale.ROOT)
  143. .contains(fragment.toLowerCase(Locale.ROOT))) {
  144. menu.setValue(c);
  145. mainLayout.setSplitPosition(0);
  146. return;
  147. }
  148. }
  149. }
  150. getMainWindow()
  151. .showNotification("No potential matc for #" + fragment);
  152. }
  153. });
  154. mainLayout.addComponent(lo);
  155. Panel bodyPanel = new Panel(bodyLayout);
  156. bodyPanel.addStyleName("light");
  157. bodyPanel.setSizeFull();
  158. mainLayout.addComponent(bodyPanel);
  159. mainLayout.setSplitPosition(30);
  160. mainWindow.setContent(mainLayout);
  161. setMainWindow(mainWindow);
  162. }
  163. private Component createTestable(Class<?> c) {
  164. try {
  165. final LegacyApplication app = (LegacyApplication) c.newInstance();
  166. app.doInit(null);
  167. Layout lo = (Layout) app.getMainWindow().getContent();
  168. lo.setParent(null);
  169. return lo;
  170. } catch (final Exception e) {
  171. try {
  172. final CustomComponent cc = (CustomComponent) c.newInstance();
  173. cc.setSizeFull();
  174. return cc;
  175. } catch (final Exception e1) {
  176. e1.printStackTrace();
  177. VerticalLayout lo = new VerticalLayout();
  178. lo.addComponent(new Label(
  179. "Cannot create application / custom component: " + e1));
  180. Link l = new Link("Try opening via app runner",
  181. new ExternalResource("../run/" + c.getName()));
  182. lo.addComponent(l);
  183. return lo;
  184. }
  185. }
  186. }
  187. // Handle menu selection and update body
  188. @Override
  189. public void valueChange(Property.ValueChangeEvent event) {
  190. bodyLayout.removeAllComponents();
  191. bodyLayout.setCaption(null);
  192. final Object o = menu.getValue();
  193. if (o != null && o instanceof Class) {
  194. final Class<?> c = (Class<?>) o;
  195. final String title = c.getName();
  196. bodyLayout.setCaption(title);
  197. bodyLayout.addComponent(createTestable(c));
  198. } else {
  199. // NOP node selected or deselected tree item
  200. }
  201. }
  202. /**
  203. * Return all testable classes within given package. Class is considered
  204. * testable if it's superclass is Application or CustomComponent.
  205. *
  206. * @param packageName
  207. * @return
  208. * @throws ClassNotFoundException
  209. */
  210. public static List<Class<?>> getTestableClassesForPackage(
  211. String packageName) throws Exception {
  212. final List<File> directories = new ArrayList<>();
  213. try {
  214. final ClassLoader cld = Thread.currentThread()
  215. .getContextClassLoader();
  216. if (cld == null) {
  217. throw new ClassNotFoundException("Can't get class loader.");
  218. }
  219. final String path = packageName.replace('.', '/');
  220. // Ask for all resources for the path
  221. final Enumeration<URL> resources = cld.getResources(path);
  222. while (resources.hasMoreElements()) {
  223. final URL url = resources.nextElement();
  224. directories.add(new File(url.getFile()));
  225. }
  226. } catch (final Exception x) {
  227. throw new Exception(
  228. packageName + " does not appear to be a valid package.");
  229. }
  230. final List<Class<?>> classes = new ArrayList<>();
  231. // For every directory identified capture all the .class files
  232. for (final File directory : directories) {
  233. if (directory.exists()) {
  234. // Get the list of the files contained in the package
  235. final String[] files = directory.list();
  236. for (int j = 0; j < files.length; j++) {
  237. // we are only interested in .class files
  238. if (files[j].endsWith(".class")) {
  239. // removes the .class extension
  240. final String p = packageName + '.'
  241. + files[j].substring(0, files[j].length() - 6);
  242. final Class<?> c = Class.forName(p);
  243. if (c.getSuperclass() != null) {
  244. if ((c.getSuperclass().equals(
  245. com.vaadin.server.VaadinSession.class))) {
  246. classes.add(c);
  247. } else if ((c.getSuperclass().equals(
  248. com.vaadin.ui.CustomComponent.class))) {
  249. classes.add(c);
  250. }
  251. }
  252. // for (Class cc : c.getInterfaces()) {
  253. // if (cc.equals(Testable.class)) {
  254. // // Class is testable
  255. // classes.add(c);
  256. // }
  257. // }
  258. }
  259. }
  260. } else {
  261. throw new ClassNotFoundException(
  262. packageName + " (" + directory.getPath()
  263. + ") does not appear to be a valid package");
  264. }
  265. }
  266. return classes;
  267. }
  268. }