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