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;
20  
21  import java.util.Collection;
22  import java.util.Collections;
23  import java.util.Map;
24  import java.util.concurrent.ConcurrentLinkedQueue;
25  import java.util.concurrent.atomic.AtomicBoolean;
26  import java.util.concurrent.atomic.AtomicInteger;
27  
28  import org.apache.maven.surefire.api.report.ReportEntry;
29  import org.apache.maven.surefire.api.report.RunMode;
30  import org.apache.maven.surefire.api.report.SimpleReportEntry;
31  import org.apache.maven.surefire.api.report.TestOutputReportEntry;
32  import org.apache.maven.surefire.api.report.TestReportListener;
33  import org.apache.maven.surefire.api.report.TestSetReportEntry;
34  import org.apache.maven.surefire.report.ClassMethodIndexer;
35  
36  import static org.apache.maven.surefire.api.util.internal.ObjectUtils.systemProps;
37  
38  /**
39   * * Represents the test-state of a testset that is run.
40   */
41  @Deprecated // remove this class after StatelessXmlReporter is capable of parallel test sets processing
42  public class TestSet {
43      private static final InheritableThreadLocal<TestSet> TEST_SET = new InheritableThreadLocal<>();
44  
45      private final String testClassName;
46  
47      private final Collection<TestMethod> testMethods = new ConcurrentLinkedQueue<>();
48  
49      private final AtomicBoolean played = new AtomicBoolean();
50  
51      private final AtomicInteger numberOfCompletedChildren = new AtomicInteger();
52  
53      // While the two parameters may seem duplicated, it is not entirely the case,
54      // since numberOfTests has the correct value from the start, while testMethods grows as method execution starts.
55  
56      private final AtomicInteger numberOfTests = new AtomicInteger();
57  
58      private final RunMode runMode;
59  
60      private final ClassMethodIndexer classMethodIndexer;
61  
62      private volatile boolean allScheduled;
63  
64      public TestSet(String testClassName, RunMode runMode, ClassMethodIndexer classMethodIndexer) {
65          this.testClassName = testClassName;
66          this.runMode = runMode;
67          this.classMethodIndexer = classMethodIndexer;
68      }
69  
70      final RunMode getRunMode() {
71          return runMode;
72      }
73  
74      final ClassMethodIndexer getClassMethodIndexer() {
75          return classMethodIndexer;
76      }
77  
78      public void replay(TestReportListener<TestOutputReportEntry> target) {
79          if (played.compareAndSet(false, true)) {
80              try {
81                  TestSetReportEntry report = createReportEntryStarted();
82  
83                  target.testSetStarting(report);
84  
85                  long startTime = 0;
86                  long endTime = 0;
87                  for (TestMethod testMethod : testMethods) {
88                      if (startTime == 0 || testMethod.getStartTime() < startTime) {
89                          startTime = testMethod.getStartTime();
90                      }
91  
92                      if (endTime == 0 || testMethod.getEndTime() > endTime) {
93                          endTime = testMethod.getEndTime();
94                      }
95  
96                      testMethod.replay(target);
97                  }
98  
99                  int elapsed = (int) (endTime - startTime);
100 
101                 report = createReportEntryCompleted(elapsed);
102 
103                 target.testSetCompleted(report);
104             } catch (Exception e) {
105                 throw new RuntimeException(e);
106             }
107         }
108     }
109 
110     public TestMethod createThreadAttachedTestMethod(ReportEntry description) {
111         TestMethod testMethod = new TestMethod(description, this);
112         addTestMethod(testMethod);
113         testMethod.attachToThread();
114         return testMethod;
115     }
116 
117     private TestSetReportEntry createReportEntryStarted() {
118         return createReportEntry(null, Collections.<String, String>emptyMap());
119     }
120 
121     private TestSetReportEntry createReportEntryCompleted(int elapsed) {
122         return createReportEntry(elapsed, systemProps());
123     }
124 
125     private TestSetReportEntry createReportEntry(Integer elapsed, Map<String, String> systemProps) {
126         return new SimpleReportEntry(
127                 runMode,
128                 classMethodIndexer.indexClass(testClassName),
129                 testClassName,
130                 null,
131                 testClassName,
132                 null,
133                 null,
134                 elapsed,
135                 systemProps);
136     }
137 
138     public void incrementTestMethodCount() {
139         numberOfTests.incrementAndGet();
140     }
141 
142     private void addTestMethod(TestMethod testMethod) {
143         testMethods.add(testMethod);
144     }
145 
146     public void incrementFinishedTests(TestReportListener reporterManager, boolean reportImmediately) {
147         numberOfCompletedChildren.incrementAndGet();
148         if (allScheduled && isAllTestsDone() && reportImmediately) {
149             replay(reporterManager);
150         }
151     }
152 
153     public void setAllScheduled(TestReportListener reporterManager) {
154         allScheduled = true;
155         if (isAllTestsDone()) {
156             replay(reporterManager);
157         }
158     }
159 
160     private boolean isAllTestsDone() {
161         return numberOfTests.get() == numberOfCompletedChildren.get();
162     }
163 
164     public void attachToThread() {
165         TEST_SET.set(this);
166     }
167 
168     public static TestSet getThreadTestSet() {
169         return TEST_SET.get();
170     }
171 }