1 /* BrowserTestRunner.java 2 Copyright (C) 2012 Red Hat, Inc. 3 4 This file is part of IcedTea. 5 6 IcedTea is free software; you can redistribute it and/or 7 modify it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, version 2. 9 10 IcedTea is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with IcedTea; see the file COPYING. If not, write to 17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 02110-1301 USA. 19 20 Linking this library statically or dynamically with other modules is 21 making a combined work based on this library. Thus, the terms and 22 conditions of the GNU General Public License cover the whole 23 combination. 24 25 As a special exception, the copyright holders of this library give you 26 permission to link this library with independent modules to produce an 27 executable, regardless of the license terms of these independent 28 modules, and to copy and distribute the resulting executable under 29 terms of your choice, provided that you also meet, for each linked 30 independent module, the terms and conditions of the license of that 31 module. An independent module is a module which is not derived from 32 or based on this library. If you modify this library, you may extend 33 this exception to your version of the library, but you are not 34 obligated to do so. If you do not wish to do so, delete this 35 exception statement from your version. 36 */ 37 38 package net.sourceforge.jnlp.browsertesting; 39 40 import java.lang.annotation.Annotation; 41 import java.lang.reflect.InvocationTargetException; 42 import net.sourceforge.jnlp.annotations.TestInBrowsers; 43 import java.lang.reflect.Method; 44 import java.util.Arrays; 45 import java.util.List; 46 import java.util.Random; 47 import net.sourceforge.jnlp.ServerAccess; 48 import org.junit.Ignore; 49 import org.junit.internal.AssumptionViolatedException; 50 import org.junit.internal.runners.model.EachTestNotifier; 51 import org.junit.runner.Description; 52 import org.junit.runner.notification.RunNotifier; 53 import org.junit.runners.BlockJUnit4ClassRunner; 54 import org.junit.runners.model.FrameworkMethod; 55 import org.junit.runners.model.InitializationError; 56 import org.junit.runners.model.Statement; 57 58 public class BrowserTestRunner extends BlockJUnit4ClassRunner { 59 BrowserTestRunner(java.lang.Class<?> testClass)60 public BrowserTestRunner(java.lang.Class<?> testClass) throws InitializationError { 61 super(testClass); 62 } 63 64 @Override runChild(FrameworkMethod method, RunNotifier notifier)65 protected void runChild(FrameworkMethod method, RunNotifier notifier) { 66 Method mm = method.getMethod(); 67 TestInBrowsers tib = mm.getAnnotation(TestInBrowsers.class); 68 injectBrowserCatched(method, Browsers.none); 69 boolean browserIgnoration = false; 70 if (tib != null) { 71 try { 72 List<Browsers> testableBrowsers = BrowserFactory.getFactory().getBrowsers(tib); 73 String mbr = System.getProperty("modified.browsers.run"); 74 if (mbr != null) { 75 if (mbr.equalsIgnoreCase("all")) { 76 if (!isBrowsersNoneSet(tib)) { 77 testableBrowsers = BrowserFactory.getFactory().getBrowsers(new Browsers[]{Browsers.all}); 78 } 79 } else if (mbr.equalsIgnoreCase("one")) { 80 //this complication here is for case like 81 // namely enumerated concrete browsers, so we want to pick up 82 // random one from those already enumerated 83 if (isBrowsersNoneSet(tib)) { 84 testableBrowsers = Arrays.asList(new Browsers[]{testableBrowsers.get(new Random().nextInt(testableBrowsers.size()))}); 85 } 86 } else if (mbr.equalsIgnoreCase("ignore")) { 87 testableBrowsers = BrowserFactory.getFactory().getBrowsers(new Browsers[]{Browsers.none}); 88 browserIgnoration = true; 89 } else { 90 ServerAccess.logErrorReprint("unrecognized value of modified.browsers.run - " + mbr); 91 } 92 } 93 for (Browsers browser : testableBrowsers) { 94 try { 95 injcetBrowser(method, browser); 96 runChildX(method, notifier, browser, browserIgnoration); 97 } catch (Exception ex) { 98 //throw new RuntimeException("unabled to inject browser", ex); 99 ServerAccess.logException(ex, true); 100 } 101 } 102 } finally { 103 injectBrowserCatched(method, Browsers.none); 104 } 105 } else { 106 runChildX(method, notifier, null, false); 107 } 108 } 109 isBrowsersNoneSet(TestInBrowsers tib)110 private boolean isBrowsersNoneSet(TestInBrowsers tib) { 111 if (tib.testIn().length == 1 && tib.testIn()[0] == Browsers.none) { 112 return true; 113 } 114 return false; 115 } 116 injectBrowserCatched(FrameworkMethod method, Browsers browser)117 private void injectBrowserCatched(FrameworkMethod method, Browsers browser) { 118 try { 119 injcetBrowser(method, browser); 120 } catch (Exception ex) { 121 //throw new RuntimeException("unabled to inject browser", ex); 122 ServerAccess.logException(ex, true); 123 } 124 } 125 injcetBrowser(FrameworkMethod method, Browsers browser)126 private void injcetBrowser(FrameworkMethod method, Browsers browser) throws IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException { 127 Method ff = method.getMethod().getDeclaringClass().getMethod("setBrowser", Browsers.class); 128 ff.invoke(null, browser); 129 } 130 runChildX(final FrameworkMethod method, RunNotifier notifier, Browsers browser, boolean browserIgnoration)131 protected void runChildX(final FrameworkMethod method, RunNotifier notifier, Browsers browser, boolean browserIgnoration) { 132 Description description = describeChild(method, browser); 133 if (method.getAnnotation(Ignore.class) != null) { 134 notifier.fireTestIgnored(description); 135 } else { 136 try { 137 runLeaf(methodBlock(method), description, notifier, browserIgnoration); 138 // ServerAccess.logOutputReprint("trying leaf"); 139 // Method m = this.getClass().getMethod("runLeaf", Statement.class, Description.class, RunNotifier.class); 140 // m.setAccessible(true); 141 // m.invoke(this, methodBlock(method), description, notifier); 142 // ServerAccess.logOutputReprint("leaf invoked"); 143 } catch (Exception ex) { 144 //throw new RuntimeException("unabled to lunch test on leaf", ex); 145 ServerAccess.logException(ex, true); 146 } 147 } 148 } 149 150 /** 151 * Runs a {@link Statement} that represents a leaf (aka atomic) test. 152 */ runLeaf(Statement statement, Description description, RunNotifier notifier, boolean ignore)153 protected final void runLeaf(Statement statement, Description description, 154 RunNotifier notifier, boolean ignore) { 155 EachTestNotifier eachNotifier = new EachTestNotifier(notifier, description); 156 eachNotifier.fireTestStarted(); 157 if (ignore) { 158 eachNotifier.fireTestIgnored(); 159 return; 160 } 161 try { 162 statement.evaluate(); 163 } catch (AssumptionViolatedException e) { 164 eachNotifier.addFailedAssumption(e); 165 } catch (Throwable e) { 166 eachNotifier.addFailure(e); 167 } finally { 168 eachNotifier.fireTestFinished(); 169 } 170 } 171 describeChild(FrameworkMethod method, Browsers browser)172 protected Description describeChild(FrameworkMethod method, Browsers browser) { 173 if (browser == null) { 174 return super.describeChild(method); 175 } else { 176 try { 177 return Description.createTestDescription(getTestClass().getJavaClass(), 178 testName(method) + " - " + browser.toString(), method.getAnnotations()); 179 } catch (Exception ex) { 180 ServerAccess.logException(ex, true); 181 return super.describeChild(method); 182 } 183 } 184 } 185 } 186