blob: c83580b91582edfeb2317d86cc8a08ce826cf403 [file] [log] [blame]
/*
* Copyright (C) 2019 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.tradefed.testtype.mobly;
import com.android.tradefed.log.LogUtil;
import com.android.tradefed.result.FailureDescription;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.TestDescription;
import com.android.tradefed.result.proto.TestRecordProto;
import com.android.tradefed.testtype.mobly.IMoblyYamlResultHandler.ITestResult;
import com.android.tradefed.testtype.mobly.MoblyYamlResultHandlerFactory.InvalidResultTypeException;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** Mobly yaml test results parser. */
public class MoblyYamlResultParser {
private static final String TYPE = "Type";
private ImmutableList.Builder<ITestInvocationListener> mListenersBuilder =
new ImmutableList.Builder<>();
private ImmutableList.Builder<ITestResult> mResultCacheBuilder = new ImmutableList.Builder<>();
private long mRunStartTime;
private long mRunEndTime;
private boolean mEnded;
private boolean mRunFailed;
public MoblyYamlResultParser(ITestInvocationListener listener) {
mListenersBuilder.add(listener);
}
public boolean parse(InputStream inputStream)
throws InvalidResultTypeException,
IllegalAccessException,
InstantiationException,
IOException {
InputStreamReader isr = new InputStreamReader(inputStream);
BufferedReader in = new BufferedReader(isr);
while (in.ready() == true) {
String line = null;
String yaml_string = "";
while (true) {
line = in.readLine();
if (line == null) continue;
if (line.equals("...")) break;
yaml_string = yaml_string + line + "\n";
}
Yaml yaml = new Yaml(new SafeConstructor());
ArrayList<ITestResult> resultCache = new ArrayList<ITestResult>();
for (Object doc : yaml.loadAll(yaml_string)) {
Map<String, Object> docMap = (Map<String, Object>) doc;
resultCache.add(parseDocumentMap(docMap));
}
reportToListeners(mListenersBuilder.build(), resultCache);
}
return mEnded;
}
public boolean getRunFailed() {
return mRunFailed;
}
@VisibleForTesting
protected ITestResult parseDocumentMap(Map<String, Object> docMap)
throws InvalidResultTypeException, IllegalAccessException, InstantiationException {
LogUtil.CLog.d("Parsed object: %s", docMap.toString());
String docType = String.valueOf(docMap.get(TYPE));
LogUtil.CLog.v("Parsing result type: %s", docType);
IMoblyYamlResultHandler resultHandler =
new MoblyYamlResultHandlerFactory().getHandler(docType);
return resultHandler.handle(docMap);
}
@VisibleForTesting
protected void reportToListeners(
List<ITestInvocationListener> listeners,
List<IMoblyYamlResultHandler.ITestResult> resultCache) {
for (IMoblyYamlResultHandler.ITestResult result : resultCache) {
switch (result.getType()) {
case RECORD:
MoblyYamlResultRecordHandler.Record record =
(MoblyYamlResultRecordHandler.Record) result;
TestDescription testDescription =
new TestDescription(record.getTestClass(), record.getTestName());
FailureDescription failureDescription =
FailureDescription.create(
record.getStackTrace(),
TestRecordProto.FailureStatus.TEST_FAILURE);
if (MoblyYamlResultRecordHandler.RecordResult.ERROR.equals(
record.getResult())) {
// Non-test failure reports indicates some early failure so we fail the run
if (!testDescription.getTestName().startsWith("test_")) {
for (ITestInvocationListener listener : listeners) {
listener.testRunFailed(failureDescription);
}
mRunFailed = true;
continue;
}
}
mRunStartTime =
mRunStartTime == 0L
? record.getBeginTime()
: Math.min(mRunStartTime, record.getBeginTime());
mRunEndTime = Math.max(mRunEndTime, record.getEndTime());
for (ITestInvocationListener listener : listeners) {
listener.testStarted(testDescription, record.getBeginTime());
if (MoblyYamlResultRecordHandler.RecordResult.SKIP.equals(
record.getResult())) {
listener.testIgnored(testDescription);
} else if (!MoblyYamlResultRecordHandler.RecordResult.PASS.equals(
record.getResult())) {
listener.testFailed(testDescription, failureDescription);
}
listener.testEnded(
testDescription,
record.getEndTime(),
new HashMap<String, String>());
}
break;
case USER_DATA:
long timestamp =
((MoblyYamlResultUserDataHandler.UserData) result).getTimeStamp();
mRunStartTime =
mRunStartTime == 0L ? timestamp : Math.min(mRunStartTime, timestamp);
break;
case CONTROLLER_INFO:
mRunEndTime =
Math.max(
mRunEndTime,
((MoblyYamlResultControllerInfoHandler.ControllerInfo) result)
.getTimeStamp());
break;
case SUMMARY:
mEnded = true;
break;
default:
// Do nothing
}
}
}
}