blob: 7209ac8d3a0f15519d5bde34b3099b9983e2b346 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* 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 com.android.compatibility.common.util;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
/**
* Utility class to add results to the report.
*/
public class ReportLog implements Serializable {
private static final String LOG_SEPARATOR = "+++";
private static final String SUMMARY_SEPARATOR = "++++";
private static final String LOG_ELEM_SEPARATOR = "|";
private static final String EMPTY_CHAR = " ";
private Result mSummary;
private final List<Result> mDetails = new ArrayList<Result>();
static class Result implements Serializable {
private String mLocation;
private String mMessage;
private double[] mValues;
private ResultType mType;
private ResultUnit mUnit;
private Double mTarget;
private Result(String location, String message, double[] values,
ResultType type, ResultUnit unit) {
this(location, message, values, null /*target*/, type, unit);
}
/**
* Creates a result object to be included in the report. Each object has a message
* describing its values and enums to interpret them. In addition, each result also includes
* class, method and line number information about the test which added this result which is
* collected by looking at the stack trace.
*
* @param message A string describing the values
* @param values An array of the values
* @param target Nullable. The target value.
* @param type Represents how to interpret the values (eg. A lower score is better)
* @param unit Represents the unit in which the values are (eg. Milliseconds)
*/
private Result(String location, String message, double[] values,
Double target, ResultType type, ResultUnit unit) {
mLocation = location;
mMessage = message;
mValues = values;
mType = type;
mUnit = unit;
mTarget = target;
}
public double getTarget() {
return mTarget;
}
public String getLocation() {
return mLocation;
}
public String getMessage() {
return mMessage;
}
public double[] getValues() {
return mValues;
}
public ResultType getType() {
return mType;
}
public ResultUnit getUnit() {
return mUnit;
}
/**
* Format:
* location|message|target|type|unit|value[s], target can be " " if there is no target set.
* log for array = classMethodName:line_number|message|unit|type|space separated values
*/
String toEncodedString() {
StringBuilder builder = new StringBuilder()
.append(mLocation)
.append(LOG_ELEM_SEPARATOR)
.append(mMessage)
.append(LOG_ELEM_SEPARATOR)
.append(mTarget != null ? mTarget : EMPTY_CHAR)
.append(LOG_ELEM_SEPARATOR)
.append(mType.name())
.append(LOG_ELEM_SEPARATOR)
.append(mUnit.name())
.append(LOG_ELEM_SEPARATOR);
for (double value : mValues) {
builder.append(value).append(" ");
}
return builder.toString();
}
static Result fromEncodedString(String encodedString) {
String[] elems = encodedString.split(Pattern.quote(LOG_ELEM_SEPARATOR));
if (elems.length < 5) {
return null;
}
String[] valueStrArray = elems[5].split(" ");
double[] valueArray = new double[valueStrArray.length];
for (int i = 0; i < valueStrArray.length; i++) {
valueArray[i] = Double.parseDouble(valueStrArray[i]);
}
return new Result(
elems[0], /*location*/
elems[1], /*message*/
valueArray, /*values*/
elems[2].equals(EMPTY_CHAR) ? null : Double.parseDouble(elems[2]), /*target*/
ResultType.valueOf(elems[3]), /*type*/
ResultUnit.valueOf(elems[4]) /*unit*/);
}
}
/**
* Adds an array of values to the report.
*/
public void addValues(String message, double[] values, ResultType type, ResultUnit unit) {
mDetails.add(new Result(Stacktrace.getTestCallerClassMethodNameLineNumber(),
message, values, type, unit));
}
/**
* Adds an array of values to the report.
*/
public void addValues(
String message, double[] values, ResultType type, ResultUnit unit, String location) {
mDetails.add(new Result(location, message, values, type, unit));
}
/**
* Adds a value to the report.
*/
public void addValue(String message, double value, ResultType type, ResultUnit unit) {
mDetails.add(new Result(Stacktrace.getTestCallerClassMethodNameLineNumber(), message,
new double[] {value}, type, unit));
}
/**
* Adds a value to the report.
*/
public void addValue(String message, double value, ResultType type,
ResultUnit unit, String location) {
mDetails.add(new Result(location, message, new double[] {value}, type, unit));
}
/**
* Sets the summary of the report.
*/
public void setSummary(String message, double value, ResultType type, ResultUnit unit) {
mSummary = new Result(Stacktrace.getTestCallerClassMethodNameLineNumber(),
message, new double[] {value}, type, unit);
}
public Result getSummary() {
return mSummary;
}
public List<Result> getDetailedMetrics() {
return new ArrayList<Result>(mDetails);
}
/**
* Parse a String encoded {@link com.android.compatibility.common.util.ReportLog}
*/
public static ReportLog fromEncodedString(String encodedString) {
ReportLog reportLog = new ReportLog();
StringTokenizer tok = new StringTokenizer(encodedString, SUMMARY_SEPARATOR);
if (tok.hasMoreTokens()) {
// Extract the summary
reportLog.mSummary = Result.fromEncodedString(tok.nextToken());
}
if (tok.hasMoreTokens()) {
// Extract the detailed results
StringTokenizer detailedTok = new StringTokenizer(tok.nextToken(), LOG_SEPARATOR);
while (detailedTok.hasMoreTokens()) {
reportLog.mDetails.add(Result.fromEncodedString(detailedTok.nextToken()));
}
}
return reportLog;
}
/**
* @return a String representation of this report or null if not collected
*/
protected String toEncodedString() {
if ((mSummary == null) && mDetails.isEmpty()) {
// just return empty string
return null;
}
StringBuilder builder = new StringBuilder();
builder.append(mSummary.toEncodedString());
builder.append(SUMMARY_SEPARATOR);
for (Result result : mDetails) {
builder.append(result.toEncodedString());
builder.append(LOG_SEPARATOR);
}
// delete the last separator
if (builder.length() >= LOG_SEPARATOR.length()) {
builder.delete(builder.length() - LOG_SEPARATOR.length(), builder.length());
}
return builder.toString();
}
}