1/**
2 * Copyright 2006-2013 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.objenesis.tck;
17
18import java.io.PrintStream;
19import java.util.ArrayList;
20import java.util.Collection;
21import java.util.HashMap;
22import java.util.Iterator;
23import java.util.List;
24import java.util.Map;
25import java.util.SortedSet;
26import java.util.TreeSet;
27
28/**
29 * Reports results from TCK as tabulated text, suitable for dumping to the console or a file and
30 * being read by a human. If can be reused to provide a summary reports of different candidates as
31 * long as the same objenesisDescription is not used twice.
32 *
33 * @author Joe Walnes
34 * @author Henri Tremblay
35 * @see TCK
36 * @see Reporter
37 */
38public class TextReporter implements Reporter {
39
40   private static class Result {
41
42      String objenesisDescription;
43
44      String candidateDescription;
45
46      boolean result;
47
48      Exception exception;
49
50      /**
51       * @param objenesisDescription Description of the tested Objenesis instance
52       * @param candidateDescription Description of the tested candidate
53       * @param result If the test is successful or not
54       * @param exception Exception that might have occured during the test
55       */
56      public Result(String objenesisDescription, String candidateDescription, boolean result,
57         Exception exception) {
58         this.objenesisDescription = objenesisDescription;
59         this.candidateDescription = candidateDescription;
60         this.result = result;
61         this.exception = exception;
62      }
63   }
64
65   private final PrintStream summary;
66
67   private final PrintStream log;
68
69   private long startTime;
70
71   private long totalTime = 0;
72
73   private int errorCount = 0;
74
75   private SortedSet allCandidates = new TreeSet();
76
77   private SortedSet allInstantiators = new TreeSet();
78
79   private String currentObjenesis;
80
81   private String currentCandidate;
82
83   private Map objenesisResults = new HashMap();
84
85   private String platformDescription;
86
87   /**
88    * @param summary Output of main report.
89    * @param log Any additional information, useful for diagnostics.
90    */
91   public TextReporter(PrintStream summary, PrintStream log) {
92      this.summary = summary;
93      this.log = log;
94   }
95
96   public void startTests(String platformDescription, Collection allCandidates,
97      Collection allInstantiators) {
98
99      // HT: in case the same reporter is reused, I'm guessing that it will
100      // always be the
101      // same platform
102      this.platformDescription = platformDescription;
103      this.allCandidates.addAll(allCandidates);
104      this.allInstantiators.addAll(allInstantiators);
105
106      for(Iterator it = allInstantiators.iterator(); it.hasNext();) {
107         objenesisResults.put(it.next(), new HashMap());
108      }
109
110      startTime = System.currentTimeMillis();
111   }
112
113   public void startTest(String candidateDescription, String objenesisDescription) {
114      currentCandidate = candidateDescription;
115      currentObjenesis = objenesisDescription;
116   }
117
118   public void result(boolean instantiatedObject) {
119      if(!instantiatedObject) {
120         errorCount++;
121      }
122      ((Map) objenesisResults.get(currentObjenesis)).put(currentCandidate, new Result(
123         currentObjenesis, currentCandidate, instantiatedObject, null));
124   }
125
126   public void exception(Exception exception) {
127
128      errorCount++;
129
130      ((Map) objenesisResults.get(currentObjenesis)).put(currentCandidate, new Result(
131         currentObjenesis, currentCandidate, false, exception));
132   }
133
134   public void endTest() {
135   }
136
137   public void endTests() {
138      totalTime += System.currentTimeMillis() - startTime;
139   }
140
141   /**
142    * Print the final summary report
143    */
144   public void printResult(boolean parentConstructorTest) {
145      // Platform
146      summary.println("Running TCK on platform: " + platformDescription);
147      summary.println();
148
149      summary.println("Not serializable parent constructor called: "
150         + (parentConstructorTest ? 'Y' : 'N'));
151      summary.println();
152
153      if(!parentConstructorTest) {
154         errorCount++;
155      }
156
157      int maxObjenesisWidth = lengthOfLongestStringIn(allInstantiators);
158      int maxCandidateWidth = lengthOfLongestStringIn(allCandidates);
159
160      // Header
161      summary.print(pad("", maxCandidateWidth) + ' ');
162      for(Iterator it = allInstantiators.iterator(); it.hasNext();) {
163         String desc = (String) it.next();
164         summary.print(pad(desc, maxObjenesisWidth) + ' ');
165      }
166      summary.println();
167
168      List exceptions = new ArrayList();
169
170      // Candidates (and keep the exceptions meanwhile)
171      for(Iterator it = allCandidates.iterator(); it.hasNext();) {
172         String candidateDesc = (String) it.next();
173         summary.print(pad(candidateDesc, maxCandidateWidth) + ' ');
174
175         for(Iterator itInst = allInstantiators.iterator(); itInst.hasNext();) {
176            String instDesc = (String) itInst.next();
177            Result result = (Result) ((Map) objenesisResults.get(instDesc)).get(candidateDesc);
178            if(result == null) {
179               summary.print(pad("N/A", maxObjenesisWidth) + " ");
180            }
181            else {
182               summary.print(pad(result.result ? "Y" : "n", maxObjenesisWidth) + " ");
183
184               if(result.exception != null) {
185                  exceptions.add(result);
186               }
187            }
188         }
189         summary.println();
190      }
191
192      summary.println();
193
194      // Final
195      if(errorCount != 0) {
196
197         for(Iterator it = exceptions.iterator(); it.hasNext();) {
198            Result element = (Result) it.next();
199            log.println("--- Candidate '" + element.candidateDescription + "', Instantiator '"
200               + element.objenesisDescription + "' ---");
201            element.exception.printStackTrace(log);
202            log.println();
203         }
204
205         log.println();
206
207         summary.println("--- FAILED: " + errorCount + " error(s) occured ---");
208      }
209      else {
210         summary.println("--- SUCCESSFUL: TCK tests passed without errors in " + totalTime + " ms");
211      }
212
213      summary.println();
214   }
215
216   private String pad(String text, int width) {
217      if(text.length() == width) {
218         return text;
219      }
220      else if(text.length() > width) {
221         return text.substring(0, width);
222      }
223      else {
224         StringBuffer padded = new StringBuffer(text);
225         while(padded.length() < width) {
226            padded.append(' ');
227         }
228         return padded.toString();
229      }
230   }
231
232   private int lengthOfLongestStringIn(Collection descriptions) {
233      int result = 0;
234      for(Iterator it = descriptions.iterator(); it.hasNext();) {
235         result = Math.max(result, ((String) it.next()).length());
236      }
237      return result;
238   }
239}
240