blob: daa21089d5483c0dd4327dd590d44a86b1f4328f [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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
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.MoblyYamlResultControllerInfoHandler.ControllerInfo;
import com.android.tradefed.testtype.mobly.MoblyYamlResultRecordHandler.Record;
import com.android.tradefed.testtype.mobly.MoblyYamlResultSummaryHandler.Summary;
import com.android.tradefed.testtype.mobly.MoblyYamlResultUserDataHandler.UserData;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/** Unit tests for {@link MoblyYamlResultParser}. */
@RunWith(JUnit4.class)
public class MoblyYamlResultParserTest {
private static final String DEFAULT_BEGIN_TIME = "1571681517464";
private static final String DEFAULT_END_TIME = "1571681520407";
private static final String DEFAULT_TEST_CLASS = "DefaultTestClass";
private static final String DEFAULT_TEST_NAME = "test_default_name";
private static final String TEST_ERROR_YAML = "/testtype/test_summary_error.yaml";
private static final String SAMPLE_STACK_TRACE =
"\"Traceback (most recent call last):\\n"
+ " File"
+ " \\\"/usr/local/google/home/yourldap/temp/sanity_suite_host.par/google3/third_party/py/mobly/base_test.py\\\"\\\n"
+ " , line 354, in _teardown_class\\n"
+ " self.teardown_class()\\n"
+ " File"
+ " \\\"/usr/local/google/home/yourldap/temp/sanity_suite_host.par/google3/javatests/com/google/android/apps/camera/functional/syshealth/sanity.py\\\"\\\n"
+ " , line 51, in teardown_class\\n"
+ " self._helper.dut.uia.press.home()\\n"
+ " File \\\"\\\n"
+ " /usr/local/google/home/yourldap/temp/sanity_suite_host.par/google3/third_party/py/mobly/controllers/android_device.py\\\"\\\n"
+ " , line 1091, in __getattr__\\n"
+ " return self.__getattribute__(name)\\n"
+ "AttributeError:\\\n"
+ " \\ 'AndroidDevice' object has no attribute 'uia'\\n"
+ "\"";
private static final Map<String, Object> mRecordMap;
static {
mRecordMap = new HashMap<>();
mRecordMap.put("Details", "test_details");
mRecordMap.put("End Time", DEFAULT_END_TIME);
mRecordMap.put("Begin Time", DEFAULT_BEGIN_TIME);
mRecordMap.put("Extra Errors", "{}");
mRecordMap.put("Extras", "null");
mRecordMap.put("Result", "PASS");
mRecordMap.put("Stacktrace", "null");
mRecordMap.put("Test Class", DEFAULT_TEST_CLASS);
mRecordMap.put("Test Name", DEFAULT_TEST_NAME);
mRecordMap.put("Type", "Record");
mRecordMap.put("UID", "null");
}
private static final String USER_DATA =
"Test Name: test_imageintent_take_photo\n"
+ "Type: UserData\n"
+ "sponge_properties:\n"
+ " dut_build_info: {build_characteristics: nosdcard, build_id: MASTER,"
+ " build_product: blueline,\n"
+ " build_type: userdebug, build_version_codename: R, build_version_sdk:"
+ " '29',\n"
+ " debuggable: '1', hardware: blueline, product_name: blueline}\n"
+ " dut_model: blueline\n"
+ " dut_serial: 827X003PY\n"
+ " dut_user_added_info: {}\n"
+ "timestamp: 1571681312605";
private static final String CONTROLLER_INFO =
"Controller Info:\n"
+ "- build_info: {build_characteristics: nosdcard, build_id: MASTER,"
+ " build_product: blueline,\n"
+ " build_type: userdebug, build_version_codename: R, build_version_sdk:"
+ " '29',\n"
+ " debuggable: '1', hardware: blueline, product_name: blueline}\n"
+ " model: blueline\n"
+ " serial: 827X003PY\n"
+ " user_added_info: {}\n"
+ "Controller Name: AndroidDevice\n"
+ "Test Class: ImageIntentSanity\n"
+ "Timestamp: 1571681322.791003\n"
+ "Type: ControllerInfo";
private static final String SUMMARY =
"{Error: 2, Executed: 3, Failed: 1, Passed: 1, Requested: 4, Skipped: 0, Type:"
+ " Summary}";
private static final String TESTNAME_LIST =
"Requested Tests: [test_imageintent_cold_launch, "
+ "test_imageintent_take_photo]\n"
+ "Type: TestNameList";
private MoblyYamlResultParser mParser;
private ITestInvocationListener mMockListener;
private ImmutableList<ITestInvocationListener> mListeners;
private ArgumentCaptor<TestDescription> mStartedDescCaptor;
private ArgumentCaptor<Long> mBeginTimeCaptor;
private ArgumentCaptor<TestDescription> mFailedDescCaptor;
private ArgumentCaptor<FailureDescription> mFailureDescriptionCaptor;
private ArgumentCaptor<TestDescription> mEndDescCaptor;
private ArgumentCaptor<Long> mEndTimeCaptor;
@Before
public void setUp() throws Exception {
mMockListener = Mockito.mock(ITestInvocationListener.class);
mListeners = ImmutableList.of(mMockListener);
setUpArgumentCaptors();
}
private void setUpArgumentCaptors() {
// Setup testStarted
mStartedDescCaptor = ArgumentCaptor.forClass(TestDescription.class);
mBeginTimeCaptor = ArgumentCaptor.forClass(Long.class);
Mockito.doNothing()
.when(mMockListener)
.testStarted(mStartedDescCaptor.capture(), mBeginTimeCaptor.capture());
// Setup testFailed
mFailedDescCaptor = ArgumentCaptor.forClass(TestDescription.class);
mFailureDescriptionCaptor = ArgumentCaptor.forClass(FailureDescription.class);
Mockito.doNothing()
.when(mMockListener)
.testFailed(mFailedDescCaptor.capture(), mFailureDescriptionCaptor.capture());
// Setup testEnded
mEndDescCaptor = ArgumentCaptor.forClass(TestDescription.class);
mEndTimeCaptor = ArgumentCaptor.forClass(Long.class);
Mockito.doNothing()
.when(mMockListener)
.testEnded(mEndDescCaptor.capture(), mEndTimeCaptor.capture(), any(Map.class));
}
@Test
public void testReportToListenersPassRecord() {
mParser = new MoblyYamlResultParser(mMockListener);
IMoblyYamlResultHandler.ITestResult passRecord =
new Record.Builder()
.setTestName(DEFAULT_TEST_NAME)
.setTestClass(DEFAULT_TEST_CLASS)
.setBeginTime(DEFAULT_BEGIN_TIME)
.setEndTime(DEFAULT_END_TIME)
.setResult(MoblyYamlResultRecordHandler.RecordResult.PASS)
.build();
List<IMoblyYamlResultHandler.ITestResult> resultCache = ImmutableList.of(passRecord);
mParser.reportToListeners(mListeners, resultCache);
assertEquals(DEFAULT_TEST_CLASS, mStartedDescCaptor.getValue().getClassName());
assertEquals(DEFAULT_TEST_NAME, mStartedDescCaptor.getValue().getTestName());
assertEquals(Long.parseLong(DEFAULT_BEGIN_TIME), (long) mBeginTimeCaptor.getValue());
verify(mMockListener, never()).testFailed(any(), anyString());
assertEquals(DEFAULT_TEST_CLASS, mEndDescCaptor.getValue().getClassName());
assertEquals(DEFAULT_TEST_NAME, mEndDescCaptor.getValue().getTestName());
assertEquals(Long.parseLong(DEFAULT_END_TIME), (long) mEndTimeCaptor.getValue());
}
@Test
public void testReportToListenersFailRecord() {
mParser = new MoblyYamlResultParser(mMockListener);
IMoblyYamlResultHandler.ITestResult failRecord =
new Record.Builder()
.setTestName(DEFAULT_TEST_NAME)
.setTestClass(DEFAULT_TEST_CLASS)
.setBeginTime(DEFAULT_BEGIN_TIME)
.setEndTime(DEFAULT_END_TIME)
.setResult(MoblyYamlResultRecordHandler.RecordResult.FAIL)
.setStackTrace(SAMPLE_STACK_TRACE)
.build();
List<IMoblyYamlResultHandler.ITestResult> resultCache = ImmutableList.of(failRecord);
mParser.reportToListeners(mListeners, resultCache);
assertEquals(DEFAULT_TEST_CLASS, mStartedDescCaptor.getValue().getClassName());
assertEquals(DEFAULT_TEST_NAME, mStartedDescCaptor.getValue().getTestName());
assertEquals(Long.parseLong(DEFAULT_BEGIN_TIME), (long) mBeginTimeCaptor.getValue());
assertEquals(DEFAULT_TEST_CLASS, mFailedDescCaptor.getValue().getClassName());
assertEquals(DEFAULT_TEST_NAME, mFailedDescCaptor.getValue().getTestName());
assertTrue(
mFailureDescriptionCaptor
.getValue()
.getErrorMessage()
.contains("Traceback (most recent call last)"));
assertTrue(
mFailureDescriptionCaptor
.getValue()
.getFailureStatus()
.equals(TestRecordProto.FailureStatus.TEST_FAILURE));
assertEquals(DEFAULT_TEST_CLASS, mEndDescCaptor.getValue().getClassName());
assertEquals(DEFAULT_TEST_NAME, mEndDescCaptor.getValue().getTestName());
assertEquals(Long.parseLong(DEFAULT_END_TIME), (long) mEndTimeCaptor.getValue());
}
@Test
public void testReportToListenersUserData() {
mParser = new MoblyYamlResultParser(mMockListener);
List<IMoblyYamlResultHandler.ITestResult> resultCache =
ImmutableList.of(new UserData.Builder().setTimestamp(DEFAULT_BEGIN_TIME).build());
mParser.reportToListeners(mListeners, resultCache);
verify(mMockListener, never()).testStarted(any(), anyLong());
verify(mMockListener, never()).testFailed(any(), anyString());
}
@Test
public void testReportToListenersControllerInfo() {
mParser = new MoblyYamlResultParser(mMockListener);
List<IMoblyYamlResultHandler.ITestResult> resultCache =
ImmutableList.of(
new ControllerInfo.Builder().setTimestamp("1571681322.791003").build());
mParser.reportToListeners(mListeners, resultCache);
verify(mMockListener, never()).testStarted(any(), anyLong());
verify(mMockListener, never()).testFailed(any(), anyString());
}
@Test
public void testParseDocumentMapRecordPass() throws Exception {
mParser = new MoblyYamlResultParser(mMockListener);
Map<String, Object> detailMap = new HashMap<>();
detailMap.put("Result", "PASS");
detailMap.put("Stacktrace", "null");
Map<String, Object> docMap = buildTestRecordDocMap(detailMap);
IMoblyYamlResultHandler.ITestResult result = mParser.parseDocumentMap(docMap);
assertTrue(result instanceof Record);
assertEquals(MoblyYamlResultRecordHandler.RecordResult.PASS, ((Record) result).getResult());
assertEquals(Long.parseLong(DEFAULT_BEGIN_TIME), ((Record) result).getBeginTime());
assertEquals(Long.parseLong(DEFAULT_END_TIME), ((Record) result).getEndTime());
assertEquals(DEFAULT_TEST_CLASS, ((Record) result).getTestClass());
assertEquals(DEFAULT_TEST_NAME, ((Record) result).getTestName());
}
@Test
public void testParseDocumentMapRecordFail() throws Exception {
mParser = new MoblyYamlResultParser(mMockListener);
Map<String, Object> detailMap = new HashMap<>();
detailMap.put("Stacktrace", SAMPLE_STACK_TRACE);
detailMap.put("Result", "FAIL");
Map<String, Object> docMap = buildTestRecordDocMap(detailMap);
IMoblyYamlResultHandler.ITestResult result = mParser.parseDocumentMap(docMap);
assertTrue(result instanceof Record);
assertEquals(MoblyYamlResultRecordHandler.RecordResult.FAIL, ((Record) result).getResult());
assertEquals(Long.parseLong(DEFAULT_BEGIN_TIME), ((Record) result).getBeginTime());
assertEquals(Long.parseLong(DEFAULT_END_TIME), ((Record) result).getEndTime());
assertEquals(DEFAULT_TEST_CLASS, ((Record) result).getTestClass());
assertEquals(DEFAULT_TEST_NAME, ((Record) result).getTestName());
assertTrue(((Record) result).getStackTrace().contains("Traceback (most recent call last)"));
}
@Test
public void testParseDocumentMapSummary() throws Exception {
mParser = new MoblyYamlResultParser(mMockListener);
Map<String, Object> docMap = new HashMap<>();
docMap.put("Type", "Summary");
docMap.put("Executed", "10");
docMap.put("Skipped", "0");
IMoblyYamlResultHandler.ITestResult result = mParser.parseDocumentMap(docMap);
assertTrue(result instanceof Summary);
assertEquals(10, ((Summary) result).getExecuted());
assertEquals(0, ((Summary) result).getSkipped());
}
@Test
public void testParseDocumentMapControllerInfo() throws Exception {
mParser = new MoblyYamlResultParser(mMockListener);
Map<String, Object> docMap = new HashMap<>();
docMap.put("Type", "ControllerInfo");
docMap.put("Timestamp", "1571681322.791003");
IMoblyYamlResultHandler.ITestResult result = mParser.parseDocumentMap(docMap);
assertTrue(result instanceof ControllerInfo);
long expTimestamp = Math.round(Double.parseDouble("1571681322.791003") * 1000);
assertEquals(expTimestamp, ((ControllerInfo) result).getTimeStamp());
}
@Test
public void testParseDocumentMapUserData() throws Exception {
mParser = new MoblyYamlResultParser(mMockListener);
Map<String, Object> docMap = new HashMap<>();
docMap.put("Type", "UserData");
docMap.put("timestamp", DEFAULT_BEGIN_TIME);
IMoblyYamlResultHandler.ITestResult result = mParser.parseDocumentMap(docMap);
assertTrue(result instanceof UserData);
assertEquals(Long.parseLong(DEFAULT_BEGIN_TIME), ((UserData) result).getTimeStamp());
}
@Test
public void testParseDocumentMapTestNameList() throws Exception {
mParser = new MoblyYamlResultParser(mMockListener);
Map<String, Object> docMap = new HashMap<>();
docMap.put("Type", "TestNameList");
IMoblyYamlResultHandler.ITestResult result = mParser.parseDocumentMap(docMap);
assertTrue(result instanceof MoblyYamlResultTestNameListHandler.TestNameList);
}
@Test
public void testParse() throws Exception {
mParser = new MoblyYamlResultParser(mMockListener);
MoblyYamlResultParser spyParser = Mockito.spy(mParser);
String passRecord = buildTestRecordString(new HashMap<>());
Map<String, Object> failMap = new HashMap<>();
failMap.put("Result", "FAIL");
failMap.put("Stracktrace", SAMPLE_STACK_TRACE);
String failRecord = buildTestRecordString(failMap);
StringBuilder strBuilder = new StringBuilder();
strBuilder.append("---\n");
strBuilder.append(TESTNAME_LIST);
strBuilder.append("\n...\n---\n");
strBuilder.append(USER_DATA);
strBuilder.append("\n...\n---\n");
strBuilder.append(passRecord);
strBuilder.append("\n...\n---\n");
strBuilder.append(failRecord);
strBuilder.append("\n...\n---\n");
strBuilder.append(CONTROLLER_INFO);
strBuilder.append("\n...\n---\n");
strBuilder.append(SUMMARY);
strBuilder.append("\n...\n");
InputStream inputStream = new ByteArrayInputStream(strBuilder.toString().getBytes());
spyParser.parse(inputStream);
verify(spyParser, times(6)).parseDocumentMap(any(Map.class));
verify(spyParser, times(6)).reportToListeners(any(), any());
}
private ImmutableMap<String, Object> buildTestRecordDocMap(Map<String, Object> propertyMap) {
Map<String, Object> map = new HashMap<>();
map.putAll(mRecordMap);
map.putAll(propertyMap);
return ImmutableMap.copyOf(map);
}
private String buildTestRecordString(Map<String, Object> detailMap) {
StringBuilder builder = new StringBuilder();
for (Iterator<Map.Entry<String, Object>> iterator =
buildTestRecordDocMap(detailMap).entrySet().iterator();
iterator.hasNext(); ) {
Map.Entry<String, Object> entry = iterator.next();
builder.append(String.format("%s: %s", entry.getKey(), entry.getValue()));
if (iterator.hasNext()) {
builder.append("\n");
}
}
return builder.toString();
}
}