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.plugin.surefire.report;
20  
21  import javax.annotation.Nonnull;
22  
23  import java.text.MessageFormat;
24  import java.util.Collections;
25  import java.util.Locale;
26  import java.util.Map;
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.StackTraceWriter;
31  import org.apache.maven.surefire.api.report.TestSetReportEntry;
32  
33  import static java.util.Collections.unmodifiableMap;
34  import static org.apache.maven.surefire.api.util.internal.StringUtils.NL;
35  import static org.apache.maven.surefire.shared.utils.StringUtils.isBlank;
36  
37  /**
38   * @author Kristian Rosenvold
39   */
40  public class WrappedReportEntry implements TestSetReportEntry {
41      private static final float ONE_SECOND = 1000.0f;
42  
43      private final ReportEntry original;
44  
45      private final ReportEntryType reportEntryType;
46  
47      private final long startTime;
48  
49      private final Integer elapsed;
50  
51      private final Utf8RecodingDeferredFileOutputStream stdout;
52  
53      private final Utf8RecodingDeferredFileOutputStream stdErr;
54  
55      private final Map<String, String> systemProperties;
56  
57      /*
58       * Rationale: The idea is to always display four digits for visually consistent output
59       * Important: Keep in sync with maven-surefire-report-plugin/src/main/resources/surefire-report.properties
60       */
61      private final MessageFormat elapsedTimeFormat = new MessageFormat(
62              "{0,choice,0#0|0.0<{0,number,0.000}|10#{0,number,0.00}|100#{0,number,0.0}|1000#{0,number,0}} s",
63              Locale.ROOT);
64  
65      public WrappedReportEntry(
66              ReportEntry original,
67              ReportEntryType reportEntryType,
68              long startTime,
69              Integer estimatedElapsed,
70              Utf8RecodingDeferredFileOutputStream stdout,
71              Utf8RecodingDeferredFileOutputStream stdErr,
72              Map<String, String> systemProperties) {
73          this.original = original;
74          this.reportEntryType = reportEntryType;
75          this.startTime = startTime;
76          this.elapsed = estimatedElapsed;
77          this.stdout = stdout;
78          this.stdErr = stdErr;
79          this.systemProperties = unmodifiableMap(systemProperties);
80      }
81  
82      public WrappedReportEntry(
83              ReportEntry original,
84              ReportEntryType reportEntryType,
85              long startTime,
86              Integer estimatedElapsed,
87              Utf8RecodingDeferredFileOutputStream stdout,
88              Utf8RecodingDeferredFileOutputStream stdErr) {
89          this(original, reportEntryType, startTime, estimatedElapsed, stdout, stdErr, Collections.emptyMap());
90      }
91  
92      public long getStartTime() {
93          return startTime;
94      }
95  
96      @Override
97      public Integer getElapsed() {
98          return elapsed;
99      }
100 
101     @Override
102     public int getElapsed(int fallback) {
103         return elapsed == null ? fallback : elapsed;
104     }
105 
106     public ReportEntryType getReportEntryType() {
107         return reportEntryType;
108     }
109 
110     public Utf8RecodingDeferredFileOutputStream getStdout() {
111         return stdout;
112     }
113 
114     public Utf8RecodingDeferredFileOutputStream getStdErr() {
115         return stdErr;
116     }
117 
118     @Override
119     public String getSourceName() {
120         return original.getSourceName();
121     }
122 
123     @Override
124     public String getSourceText() {
125         return original.getSourceText();
126     }
127 
128     @Override
129     public String getName() {
130         return original.getName();
131     }
132 
133     @Override
134     public String getNameText() {
135         return original.getNameText();
136     }
137 
138     public String getClassMethodName() {
139         return original.getSourceName() + "." + original.getName();
140     }
141 
142     public String getFullName() {
143         return getName() == null ? getSourceName() : getClassMethodName();
144     }
145 
146     @Override
147     public String getGroup() {
148         return original.getGroup();
149     }
150 
151     @Override
152     public StackTraceWriter getStackTraceWriter() {
153         return original.getStackTraceWriter();
154     }
155 
156     @Override
157     public String getMessage() {
158         return original.getMessage();
159     }
160 
161     public String getStackTrace(boolean trimStackTrace) {
162         StackTraceWriter w = original.getStackTraceWriter();
163         return w == null ? null : (trimStackTrace ? w.writeTrimmedTraceToString() : w.writeTraceToString());
164     }
165 
166     public String elapsedTimeAsString() {
167         return getElapsed() != null ? elapsedTimeFormat.format(new Object[] {getElapsed() / ONE_SECOND}) : null;
168     }
169 
170     String getReportSourceName() {
171         String sourceName = getSourceName();
172         String sourceText = getSourceText();
173         return isBlank(sourceText) ? sourceName : sourceText;
174     }
175 
176     String getReportSourceName(String suffix) {
177         return isBlank(suffix) ? getReportSourceName() : getReportSourceName() + "(" + suffix + ")";
178     }
179 
180     String getSourceName(String suffix) {
181         return isBlank(suffix) ? getSourceName() : getSourceName() + "(" + suffix + ")";
182     }
183 
184     String getSourceQualifiedName(String suffix) {
185         String qualifiedName = original.getSourceQualifiedName();
186         if (qualifiedName != null) {
187             return isBlank(suffix) ? qualifiedName : qualifiedName + "(" + suffix + ")";
188         }
189         // Fall back to pre-existing behaviour: sourceText if set, else sourceName (with suffix)
190         String sourceText = getSourceText();
191         return sourceText != null ? sourceText : getSourceName(suffix);
192     }
193 
194     String getReportName() {
195         String name = getName();
196         String nameText = getNameText();
197         return isBlank(nameText) ? name : nameText;
198     }
199 
200     public String getOutput(boolean trimStackTrace) {
201         String outputLine =
202                 getElapsedTimeSummary() + " <<< " + getReportEntryType().name() + "!";
203         String trimmedStackTrace = getStackTrace(trimStackTrace);
204         return trimmedStackTrace == null ? outputLine : outputLine + NL + trimmedStackTrace;
205     }
206 
207     public String getElapsedTimeVerbose() {
208         return "Time elapsed: " + (getElapsed() != null ? elapsedTimeAsString() : "(unknown)");
209     }
210 
211     public String getElapsedTimeSummary() {
212         return getFullName() + " -- " + getElapsedTimeVerbose();
213     }
214 
215     public boolean isErrorOrFailure() {
216         ReportEntryType thisType = getReportEntryType();
217         return ReportEntryType.FAILURE == thisType || ReportEntryType.ERROR == thisType;
218     }
219 
220     public boolean isSkipped() {
221         return ReportEntryType.SKIPPED == getReportEntryType();
222     }
223 
224     public boolean isSucceeded() {
225         return ReportEntryType.SUCCESS == getReportEntryType();
226     }
227 
228     @Override
229     public String getNameWithGroup() {
230         return original.getNameWithGroup();
231     }
232 
233     @Override
234     public String getReportNameWithGroup() {
235         String reportNameWithGroup = original.getReportNameWithGroup();
236 
237         if (isBlank(reportNameWithGroup)) {
238             return getNameWithGroup();
239         }
240 
241         return reportNameWithGroup;
242     }
243 
244     @Nonnull
245     @Override
246     public RunMode getRunMode() {
247         return original.getRunMode();
248     }
249 
250     @Override
251     public Long getTestRunId() {
252         return original.getTestRunId();
253     }
254 
255     @Override
256     public Map<String, String> getSystemProperties() {
257         return systemProperties;
258     }
259 }