View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.surefire.junitcore.pc;
20  
21  import java.util.HashMap;
22  import java.util.Map;
23  
24  import org.apache.maven.surefire.api.testset.TestSetFailedException;
25  import org.apache.maven.surefire.junitcore.JUnitCoreParameters;
26  import org.junit.AfterClass;
27  import org.junit.BeforeClass;
28  import org.junit.Rule;
29  import org.junit.experimental.theories.DataPoint;
30  import org.junit.experimental.theories.Theories;
31  import org.junit.experimental.theories.Theory;
32  import org.junit.rules.ExpectedException;
33  import org.junit.runner.RunWith;
34  
35  import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.PARALLEL_KEY;
36  import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.THREADCOUNTCLASSES_KEY;
37  import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.THREADCOUNTSUITES_KEY;
38  import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.THREADCOUNT_KEY;
39  import static org.apache.maven.surefire.junitcore.pc.ParallelComputerUtil.overrideAvailableProcessors;
40  import static org.apache.maven.surefire.junitcore.pc.ParallelComputerUtil.resolveConcurrency;
41  import static org.apache.maven.surefire.junitcore.pc.ParallelComputerUtil.setDefaultAvailableProcessors;
42  import static org.hamcrest.core.Is.is;
43  import static org.junit.Assert.assertFalse;
44  import static org.junit.Assert.assertThat;
45  import static org.junit.Assert.assertTrue;
46  
47  /**
48   * Testing an algorithm in {@link ParallelComputerUtil} which configures optimized thread resources in ParallelComputer
49   * by given {@link org.apache.maven.surefire.junitcore.JUnitCoreParameters}.
50   *
51   * @author Tibor Digana (tibor17)
52   * @see ParallelComputerUtil
53   * @since 2.17
54   */
55  @RunWith(Theories.class)
56  @SuppressWarnings("checkstyle:magicnumber")
57  public final class OptimizedParallelComputerTest {
58      @DataPoint
59      public static final int CPU_1 = 1;
60  
61      @DataPoint
62      public static final int CPU_4 = 4;
63  
64      @Rule
65      public final ExpectedException exception = ExpectedException.none();
66  
67      @BeforeClass
68      public static void beforeClass() {
69          overrideAvailableProcessors(1);
70      }
71  
72      @AfterClass
73      public static void afterClass() {
74          setDefaultAvailableProcessors();
75      }
76  
77      @Theory
78      public void threadCountSuites(int cpu) throws TestSetFailedException {
79          overrideAvailableProcessors(cpu);
80          Map<String, String> properties = new HashMap<>();
81          properties.put(PARALLEL_KEY, "suites");
82          properties.put(THREADCOUNT_KEY, "3");
83          JUnitCoreParameters params = new JUnitCoreParameters(properties);
84          RunnerCounter counter = new RunnerCounter(5, 10, 20);
85          Concurrency concurrency = resolveConcurrency(params, counter);
86          assertTrue(params.isParallelSuites());
87          assertFalse(params.isParallelClasses());
88          assertFalse(params.isParallelMethods());
89          assertThat(concurrency.capacity, is(0));
90          assertThat(concurrency.suites, is((int) Math.min(3 * cpu, counter.suites)));
91          assertThat(concurrency.classes, is(0));
92          assertThat(concurrency.methods, is(0));
93      }
94  
95      @Theory
96      public void threadCountClasses(int cpu) throws TestSetFailedException {
97          overrideAvailableProcessors(cpu);
98          Map<String, String> properties = new HashMap<>();
99          properties.put(PARALLEL_KEY, "classes");
100         properties.put(THREADCOUNT_KEY, "3");
101         JUnitCoreParameters params = new JUnitCoreParameters(properties);
102         RunnerCounter counter = new RunnerCounter(1, 5, 10);
103         Concurrency concurrency = resolveConcurrency(params, counter);
104         assertFalse(params.isParallelSuites());
105         assertTrue(params.isParallelClasses());
106         assertFalse(params.isParallelMethods());
107         assertThat(concurrency.capacity, is(0));
108         assertThat(concurrency.suites, is(0));
109         assertThat(concurrency.classes, is((int) Math.min(3 * cpu, counter.classes)));
110         assertThat(concurrency.methods, is(0));
111     }
112 
113     @Theory
114     public void threadCountMethods(int cpu) throws TestSetFailedException {
115         overrideAvailableProcessors(cpu);
116         Map<String, String> properties = new HashMap<>();
117         properties.put(PARALLEL_KEY, "methods");
118         properties.put(THREADCOUNT_KEY, "3");
119         JUnitCoreParameters params = new JUnitCoreParameters(properties);
120         RunnerCounter counter = new RunnerCounter(1, 2, 5);
121         Concurrency concurrency = resolveConcurrency(params, counter);
122         assertFalse(params.isParallelSuites());
123         assertFalse(params.isParallelClasses());
124         assertTrue(params.isParallelMethods());
125         assertThat(concurrency.capacity, is(0));
126         assertThat(concurrency.suites, is(0));
127         assertThat(concurrency.classes, is(0));
128         assertThat(concurrency.methods, is((int) Math.min(3 * cpu, counter.methods)));
129     }
130 
131     @Theory
132     public void threadCountBoth(int cpu) throws TestSetFailedException {
133         overrideAvailableProcessors(cpu);
134         Map<String, String> properties = new HashMap<>();
135         properties.put(PARALLEL_KEY, "both");
136         properties.put(THREADCOUNT_KEY, "3");
137         JUnitCoreParameters params = new JUnitCoreParameters(properties);
138         RunnerCounter counter = new RunnerCounter(1, 2, 5);
139         Concurrency concurrency = resolveConcurrency(params, counter);
140         assertFalse(params.isParallelSuites());
141         assertTrue(params.isParallelClasses());
142         assertTrue(params.isParallelMethods());
143         assertThat(concurrency.capacity, is(3 * cpu));
144         assertThat(concurrency.suites, is(0));
145         assertThat(concurrency.classes, is((int) Math.min((3d / 2) * cpu, 2)));
146         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
147     }
148 
149     @Theory
150     public void threadCountClassesAndMethods(int cpu) throws TestSetFailedException {
151         overrideAvailableProcessors(cpu);
152         Map<String, String> properties = new HashMap<>();
153         properties.put(PARALLEL_KEY, "classesAndMethods");
154         properties.put(THREADCOUNT_KEY, "3");
155         JUnitCoreParameters params = new JUnitCoreParameters(properties);
156         RunnerCounter counter = new RunnerCounter(1, 2, 5);
157         Concurrency concurrency = resolveConcurrency(params, counter);
158         assertFalse(params.isParallelSuites());
159         assertTrue(params.isParallelClasses());
160         assertTrue(params.isParallelMethods());
161         assertThat(concurrency.capacity, is(3 * cpu));
162         assertThat(concurrency.suites, is(0));
163         assertThat(concurrency.classes, is((int) Math.min((3d / 2) * cpu, 2)));
164         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
165     }
166 
167     @Theory
168     public void threadCountSuitesAndMethods(int cpu) throws TestSetFailedException {
169         overrideAvailableProcessors(cpu);
170         Map<String, String> properties = new HashMap<>();
171         properties.put(PARALLEL_KEY, "suitesAndMethods");
172         properties.put(THREADCOUNT_KEY, "3");
173         JUnitCoreParameters params = new JUnitCoreParameters(properties);
174         RunnerCounter counter = new RunnerCounter(2, 3, 5);
175         Concurrency concurrency = resolveConcurrency(params, counter);
176         assertTrue(params.isParallelSuites());
177         assertFalse(params.isParallelClasses());
178         assertTrue(params.isParallelMethods());
179         assertThat(concurrency.capacity, is(3 * cpu));
180         assertThat(concurrency.suites, is((int) Math.min((3d / 2) * cpu, 2)));
181         assertThat(concurrency.classes, is(0));
182         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
183     }
184 
185     @Theory
186     public void threadCountSuitesAndClasses(int cpu) throws TestSetFailedException {
187         overrideAvailableProcessors(cpu);
188         Map<String, String> properties = new HashMap<>();
189         properties.put(PARALLEL_KEY, "suitesAndClasses");
190         properties.put(THREADCOUNT_KEY, "3");
191         JUnitCoreParameters params = new JUnitCoreParameters(properties);
192         RunnerCounter counter = new RunnerCounter(2, 5, 20);
193         Concurrency concurrency = resolveConcurrency(params, counter);
194         assertTrue(params.isParallelSuites());
195         assertTrue(params.isParallelClasses());
196         assertFalse(params.isParallelMethods());
197         assertThat(concurrency.capacity, is(3 * cpu));
198         assertThat(concurrency.suites, is((int) Math.min((2d * 3 / 7) * cpu, 2)));
199         assertThat(concurrency.classes, is(Integer.MAX_VALUE));
200         assertThat(concurrency.methods, is(0));
201     }
202 
203     @Theory
204     public void threadCountAll(int cpu) throws TestSetFailedException {
205         overrideAvailableProcessors(cpu);
206         Map<String, String> properties = new HashMap<>();
207         properties.put(PARALLEL_KEY, "all");
208         properties.put(THREADCOUNT_KEY, "3");
209         JUnitCoreParameters params = new JUnitCoreParameters(properties);
210         RunnerCounter counter = new RunnerCounter(2, 5, 20);
211         Concurrency concurrency = resolveConcurrency(params, counter);
212         assertTrue(params.isParallelSuites());
213         assertTrue(params.isParallelClasses());
214         assertTrue(params.isParallelMethods());
215         assertThat(concurrency.capacity, is(3 * cpu));
216         assertThat(concurrency.suites, is((int) Math.min((2d * 3 / 11) * cpu, 2)));
217         assertThat(concurrency.classes, is((int) Math.min((5d * 3 / 11) * cpu, 5)));
218         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
219     }
220 
221     @Theory
222     public void reusableThreadCountSuitesAndClasses(int cpu) throws TestSetFailedException {
223         // 4 * cpu to 5 * cpu threads to run test classes
224         overrideAvailableProcessors(cpu);
225         Map<String, String> properties = new HashMap<>();
226         properties.put(PARALLEL_KEY, "suitesAndClasses");
227         properties.put(THREADCOUNT_KEY, "6");
228         properties.put(THREADCOUNTSUITES_KEY, "2");
229         JUnitCoreParameters params = new JUnitCoreParameters(properties);
230         RunnerCounter counter = new RunnerCounter(3, 5, 20);
231         Concurrency concurrency = resolveConcurrency(params, counter);
232         assertTrue(params.isParallelSuites());
233         assertTrue(params.isParallelClasses());
234         assertFalse(params.isParallelMethods());
235         assertThat(concurrency.capacity, is(6 * cpu));
236         assertThat(concurrency.suites, is(Math.min(2 * cpu, 3)));
237         assertThat(concurrency.classes, is(Integer.MAX_VALUE));
238         assertThat(concurrency.methods, is(0));
239     }
240 
241     @Theory
242     public void reusableThreadCountSuitesAndMethods(int cpu) throws TestSetFailedException {
243         // 4 * cpu to 5 * cpu threads to run test methods
244         overrideAvailableProcessors(cpu);
245         Map<String, String> properties = new HashMap<>();
246         properties.put(PARALLEL_KEY, "suitesAndMethods");
247         properties.put(THREADCOUNT_KEY, "6");
248         properties.put(THREADCOUNTSUITES_KEY, "2");
249         JUnitCoreParameters params = new JUnitCoreParameters(properties);
250         RunnerCounter counter = new RunnerCounter(3, 5, 20);
251         Concurrency concurrency = resolveConcurrency(params, counter);
252         assertTrue(params.isParallelSuites());
253         assertFalse(params.isParallelClasses());
254         assertTrue(params.isParallelMethods());
255         assertThat(concurrency.capacity, is(6 * cpu));
256         assertThat(concurrency.suites, is(Math.min(2 * cpu, 3)));
257         assertThat(concurrency.classes, is(0));
258         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
259     }
260 
261     @Theory
262     public void reusableThreadCountClassesAndMethods(int cpu) throws TestSetFailedException {
263         // 4 * cpu to 5 * cpu threads to run test methods
264         overrideAvailableProcessors(cpu);
265         Map<String, String> properties = new HashMap<>();
266         properties.put(PARALLEL_KEY, "classesAndMethods");
267         properties.put(THREADCOUNT_KEY, "6");
268         properties.put(THREADCOUNTCLASSES_KEY, "2");
269         JUnitCoreParameters params = new JUnitCoreParameters(properties);
270         RunnerCounter counter = new RunnerCounter(3, 5, 20);
271         Concurrency concurrency = resolveConcurrency(params, counter);
272         assertFalse(params.isParallelSuites());
273         assertTrue(params.isParallelClasses());
274         assertTrue(params.isParallelMethods());
275         assertThat(concurrency.capacity, is(6 * cpu));
276         assertThat(concurrency.suites, is(0));
277         assertThat(concurrency.classes, is(Math.min(2 * cpu, 5)));
278         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
279     }
280 
281     @Theory
282     public void reusableThreadCountAll(int cpu) throws TestSetFailedException {
283         // 8 * cpu to 13 * cpu threads to run test methods
284         overrideAvailableProcessors(cpu);
285         Map<String, String> properties = new HashMap<>();
286         properties.put(PARALLEL_KEY, "all");
287         properties.put(THREADCOUNT_KEY, "14");
288         properties.put(THREADCOUNTSUITES_KEY, "2");
289         properties.put(THREADCOUNTCLASSES_KEY, "4");
290         JUnitCoreParameters params = new JUnitCoreParameters(properties);
291         RunnerCounter counter = new RunnerCounter(3, 5, 20);
292         Concurrency concurrency = resolveConcurrency(params, counter);
293         assertTrue(params.isParallelSuites());
294         assertTrue(params.isParallelClasses());
295         assertTrue(params.isParallelMethods());
296         assertThat(concurrency.capacity, is(14 * cpu));
297         assertThat(concurrency.suites, is(Math.min(2 * cpu, 3)));
298         assertThat(concurrency.classes, is(Math.min(4 * cpu, 5)));
299         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
300     }
301 }