blob: 1c6b19693e82e6e34ac5ae2fce4764e4b45a4acc [file] [log] [blame]
/**
* Copyright 2006-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.objenesis.tck;
import org.objenesis.Objenesis;
import java.io.PrintStream;
import java.util.*;
/**
* Reports results from TCK as tabulated text, suitable for dumping to the console or a file and
* being read by a human. It can be reused to provide a summary reports of different candidates as
* long as the same <code>objenesisDescription</code> is not used twice.
*
* @author Joe Walnes
* @author Henri Tremblay
* @see TCK
* @see Reporter
*/
public class TextReporter implements Reporter {
private static class Result {
String objenesisDescription;
String candidateDescription;
boolean result;
Exception exception;
/**
* @param objenesisDescription Description of the tested Objenesis instance
* @param candidateDescription Description of the tested candidate
* @param result If the test is successful or not
* @param exception Exception that might have occured during the test
*/
public Result(String objenesisDescription, String candidateDescription, boolean result,
Exception exception) {
this.objenesisDescription = objenesisDescription;
this.candidateDescription = candidateDescription;
this.result = result;
this.exception = exception;
}
}
private final PrintStream summary;
private final PrintStream log;
private long startTime;
private long totalTime = 0;
private int errorCount = 0;
private SortedMap<String, Object> allCandidates = new TreeMap<String, Object>();
private SortedMap<String, Object> allInstantiators = new TreeMap<String, Object>();
private String currentObjenesis;
private String currentCandidate;
private Map<Object, Map<String, Result>> objenesisResults = new HashMap<Object, Map<String, Result>>();
private String platformDescription;
/**
* @param summary Output of main report.
* @param log Any additional information, useful for diagnostics.
*/
public TextReporter(PrintStream summary, PrintStream log) {
this.summary = summary;
this.log = log;
}
public int getErrorCount() {
return errorCount;
}
public void startTests(String platformDescription, Map<String, Object> allCandidates,
Map<String, Object> allInstantiators) {
// HT: in case the same reporter is reused, I'm guessing that it will
// always be the same platform
this.platformDescription = platformDescription;
this.allCandidates.putAll(allCandidates);
this.allInstantiators.putAll(allInstantiators);
for(String desc : allInstantiators.keySet()) {
objenesisResults.put(desc, new HashMap<String, Result>());
}
startTime = System.currentTimeMillis();
}
public void startTest(String candidateDescription, String objenesisDescription) {
currentCandidate = candidateDescription;
currentObjenesis = objenesisDescription;
}
public void result(boolean instantiatedObject) {
if(!instantiatedObject) {
errorCount++;
}
objenesisResults.get(currentObjenesis).put(currentCandidate,
new Result(
currentObjenesis, currentCandidate, instantiatedObject, null));
}
public void exception(Exception exception) {
errorCount++;
objenesisResults.get(currentObjenesis).put(currentCandidate,
new Result(
currentObjenesis, currentCandidate, false, exception));
}
public void endTest() {
}
public void endTests() {
totalTime += System.currentTimeMillis() - startTime;
}
/**
* Print the final summary report
*
* @param parentConstructorTest If the test checking that the none serializable constructor was called was successful
*/
public void printResult(boolean parentConstructorTest) {
// Platform
summary.println("Running TCK on platform: " + platformDescription);
summary.println();
// Instantiator implementations
summary.println("Instantiators used: ");
for(Map.Entry<String, Object> o : allInstantiators.entrySet()) {
String inst = ((Objenesis) o.getValue()).getInstantiatorOf(String.class).getClass()
.getSimpleName();
summary.println(" " + o.getKey() + ": " + inst);
}
summary.println();
// Parent constructor special test
summary.println("Not serializable parent constructor called as expected: "
+ (parentConstructorTest ? 'Y' : 'N'));
summary.println();
if(!parentConstructorTest) {
errorCount++;
}
Set<String> instantiators = this.allInstantiators.keySet();
Set<String> candidates = this.allCandidates.keySet();
int maxObjenesisWidth = lengthOfLongestStringIn(instantiators);
int maxCandidateWidth = lengthOfLongestStringIn(candidates);
// Strategy used
summary.print(pad("", maxCandidateWidth) + ' ');
for(String desc : instantiators) {
summary.print(pad(desc, maxObjenesisWidth) + ' ');
}
summary.println();
List<Result> exceptions = new ArrayList<Result>();
// Candidates (and keep the exceptions meanwhile)
for(String candidateDesc : candidates) {
summary.print(pad(candidateDesc, maxCandidateWidth) + ' ');
for(String instDesc : instantiators) {
Result result = objenesisResults.get(instDesc).get(candidateDesc);
if(result == null) {
summary.print(pad("N/A", maxObjenesisWidth) + " ");
}
else {
summary.print(pad(result.result ? "Y" : "n", maxObjenesisWidth) + " ");
if(result.exception != null) {
exceptions.add(result);
}
}
}
summary.println();
}
summary.println();
// Final
if(errorCount != 0) {
for(Result element : exceptions) {
log.println("--- Candidate '" + element.candidateDescription + "', Instantiator '"
+ element.objenesisDescription + "' ---");
element.exception.printStackTrace(log);
log.println();
}
log.println();
summary.println("--- FAILED: " + errorCount + " error(s) occured ---");
}
else {
summary.println("--- SUCCESSFUL: TCK tests passed without errors in " + totalTime + " ms");
}
summary.println();
}
/**
* Return true if the reporter has registered some errors
*
* @return if there was errors during execution
*/
public boolean hasErrors() {
return errorCount != 0;
}
private String pad(String text, int width) {
if(text.length() == width) {
return text;
}
else if(text.length() > width) {
return text.substring(0, width);
}
else {
StringBuilder padded = new StringBuilder(text);
while(padded.length() < width) {
padded.append(' ');
}
return padded.toString();
}
}
private int lengthOfLongestStringIn(Collection<String> descriptions) {
int result = 0;
for(Iterator<String> it = descriptions.iterator(); it.hasNext();) {
result = Math.max(result, it.next().length());
}
return result;
}
}