Class | Line # | Actions | |||||
---|---|---|---|---|---|---|---|
XWikiExecutorSuite | 52 | 45 | 0% | 16 | 12 | ||
XWikiExecutorSuite.Executors | 69 | 0 | - | 0 | 0 | ||
XWikiExecutorSuite.PreStart | 79 | 0 | - | 0 | 0 | ||
XWikiExecutorSuite.PostStart | 85 | 0 | - | 0 | 0 |
1 | /* | |
2 | * See the NOTICE file distributed with this work for additional | |
3 | * information regarding copyright ownership. | |
4 | * | |
5 | * This is free software; you can redistribute it and/or modify it | |
6 | * under the terms of the GNU Lesser General Public License as | |
7 | * published by the Free Software Foundation; either version 2.1 of | |
8 | * the License, or (at your option) any later version. | |
9 | * | |
10 | * This software 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 | * Lesser General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU Lesser General Public | |
16 | * License along with this software; if not, write to the Free | |
17 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | |
18 | * 02110-1301 USA, or see the FSF site: http://www.fsf.org. | |
19 | */ | |
20 | package org.xwiki.test.integration; | |
21 | ||
22 | import java.lang.annotation.ElementType; | |
23 | import java.lang.annotation.Retention; | |
24 | import java.lang.annotation.RetentionPolicy; | |
25 | import java.lang.annotation.Target; | |
26 | import java.lang.reflect.Method; | |
27 | import java.util.ArrayList; | |
28 | import java.util.List; | |
29 | ||
30 | import org.junit.extensions.cpsuite.ClasspathSuite; | |
31 | import org.junit.runner.Description; | |
32 | import org.junit.runner.Runner; | |
33 | import org.junit.runner.manipulation.Filter; | |
34 | import org.junit.runner.manipulation.NoTestsRemainException; | |
35 | import org.junit.runner.notification.RunNotifier; | |
36 | import org.junit.runners.model.InitializationError; | |
37 | import org.junit.runners.model.RunnerBuilder; | |
38 | import org.slf4j.Logger; | |
39 | import org.slf4j.LoggerFactory; | |
40 | ||
41 | /** | |
42 | * Starts/Stop XWiki before/after all tests and run all tests found in the current classloader using <a | |
43 | * href="http://www.johanneslink.net/projects/cpsuite.jsp">cpsuite</a> (we extend it). Tests can be filtered by passing | |
44 | * the "pattern" System Property. | |
45 | * <p> | |
46 | * More details on the "pattern" System Property, its syntax and examples are found in the | |
47 | * {@link XWikiExecutorTestMethodFilter} class. | |
48 | * | |
49 | * @version $Id: 1dcadc6663da5a9b6d5917e6801c6196ca04ebfe $ | |
50 | * @since 3.0RC1 | |
51 | */ | |
52 | public class XWikiExecutorSuite extends ClasspathSuite | |
53 | { | |
54 | public static final String PATTERN = String.format(".*(%s)", System.getProperty("pattern", "")); | |
55 | ||
56 | protected static final Logger LOGGER = LoggerFactory.getLogger(XWikiExecutorSuite.class); | |
57 | ||
58 | private static final Filter METHOD_FILTER = new XWikiExecutorTestMethodFilter(PATTERN); | |
59 | ||
60 | private List<XWikiExecutor> executors = new ArrayList<XWikiExecutor>(); | |
61 | ||
62 | 18 | public XWikiExecutorSuite(Class< ? > klass, RunnerBuilder builder) throws InitializationError |
63 | { | |
64 | 18 | super(klass, builder); |
65 | } | |
66 | ||
67 | @Retention(RetentionPolicy.RUNTIME) | |
68 | @Target(ElementType.TYPE) | |
69 | public @interface Executors | |
70 | { | |
71 | /** | |
72 | * @return the number of executors to run | |
73 | */ | |
74 | public int value() default 1; | |
75 | } | |
76 | ||
77 | @Retention(RetentionPolicy.RUNTIME) | |
78 | @Target(ElementType.METHOD) | |
79 | public static @interface PreStart | |
80 | { | |
81 | } | |
82 | ||
83 | @Retention(RetentionPolicy.RUNTIME) | |
84 | @Target(ElementType.METHOD) | |
85 | public static @interface PostStart | |
86 | { | |
87 | } | |
88 | ||
89 | 15 | public List<XWikiExecutor> getExecutors() |
90 | { | |
91 | 15 | return this.executors; |
92 | } | |
93 | ||
94 | 18 | @Override |
95 | protected List<Runner> getChildren() | |
96 | { | |
97 | 18 | List<Runner> runners = new ArrayList<Runner>(); |
98 | ||
99 | // Filter the test classes to run. | |
100 | 18 | for (Runner runner : super.getChildren()) { |
101 | 114 | Description description = runner.getDescription(); |
102 | 114 | String runnerName = description.getClassName(); |
103 | ||
104 | 114 | if (runnerName.matches(PATTERN)) { |
105 | // If the entire test class matches, add it. | |
106 | 114 | runners.add(runner); |
107 | } else { | |
108 | // Otherwise, filter the test methods to run. | |
109 | 0 | try { |
110 | 0 | METHOD_FILTER.apply(runner); |
111 | // If the runner still has tests remaining after the filtering, add it. | |
112 | 0 | runners.add(runner); |
113 | } catch (NoTestsRemainException e) { | |
114 | 0 | LOGGER.info("Skipping test class: {}", description.getClassName()); |
115 | } | |
116 | } | |
117 | } | |
118 | ||
119 | 18 | return runners; |
120 | } | |
121 | ||
122 | /** | |
123 | * Called before test execution. | |
124 | */ | |
125 | 18 | protected void beforeTests() |
126 | { | |
127 | // Construct as many executors as specified in the Executors annotation or 1 if annotation is not present. | |
128 | 18 | int executorNb = 1; |
129 | 18 | Executors executorsAnnotation = getTestClass().getJavaClass().getAnnotation(Executors.class); |
130 | 18 | if (executorsAnnotation != null) { |
131 | 1 | executorNb = executorsAnnotation.value(); |
132 | } | |
133 | ||
134 | 37 | for (int i = 0; i < executorNb; i++) { |
135 | 19 | this.executors.add(new XWikiExecutor(i)); |
136 | } | |
137 | ||
138 | // Callback to setup executors in the suite class before containers are started | |
139 | 18 | try { |
140 | 18 | for (Method method : getTestClass().getJavaClass().getMethods()) { |
141 | 174 | PreStart preStartAnnotation = method.getAnnotation(PreStart.class); |
142 | 174 | if (preStartAnnotation != null) { |
143 | // Call it! | |
144 | 6 | Object instance = getTestClass().getJavaClass().newInstance(); |
145 | 6 | method.invoke(instance, this.executors); |
146 | } | |
147 | } | |
148 | } catch (Exception e) { | |
149 | 0 | throw new RuntimeException("Failed to initialize XWiki Executors before start", e); |
150 | } | |
151 | ||
152 | 18 | try { |
153 | 18 | for (XWikiExecutor executor : this.executors) { |
154 | 19 | executor.start(); |
155 | } | |
156 | } catch (Exception e) { | |
157 | 0 | throw new RuntimeException("Failed to start XWiki", e); |
158 | } | |
159 | ||
160 | // Callback to setup executors in the suite class after containers have been started | |
161 | 18 | try { |
162 | 18 | for (Method method : getTestClass().getJavaClass().getMethods()) { |
163 | 174 | PostStart postStartAnnotation = method.getAnnotation(PostStart.class); |
164 | 174 | if (postStartAnnotation != null) { |
165 | // Call it! | |
166 | 0 | Object instance = getTestClass().getJavaClass().newInstance(); |
167 | 0 | method.invoke(instance, this.executors); |
168 | } | |
169 | } | |
170 | } catch (Exception e) { | |
171 | 0 | throw new RuntimeException("Failed to initialize XWiki Executors after start", e); |
172 | } | |
173 | } | |
174 | ||
175 | /** | |
176 | * Called after test execution. | |
177 | */ | |
178 | 3 | protected void afterTests() |
179 | { | |
180 | 3 | try { |
181 | 3 | for (XWikiExecutor executor : this.executors) { |
182 | 4 | executor.stop(); |
183 | } | |
184 | } catch (Exception e) { | |
185 | 0 | throw new RuntimeException("Failed to stop XWiki", e); |
186 | } | |
187 | } | |
188 | ||
189 | 18 | @Override |
190 | public void run(RunNotifier notifier) | |
191 | { | |
192 | 18 | beforeTests(); |
193 | ||
194 | 18 | try { |
195 | 18 | super.run(notifier); |
196 | } finally { | |
197 | 18 | afterTests(); |
198 | } | |
199 | } | |
200 | } |