| /* |
| * 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.device.metric; |
| |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertTrue; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.times; |
| import static org.mockito.Mockito.verify; |
| import static org.mockito.Mockito.when; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| import org.mockito.Mock; |
| import org.mockito.Mockito; |
| import org.mockito.MockitoAnnotations; |
| |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertTrue; |
| |
| import com.android.ddmlib.IDevice; |
| import com.android.tradefed.config.ConfigurationDef; |
| import com.android.tradefed.device.ILogcatReceiver; |
| import com.android.tradefed.device.ITestDevice; |
| import com.android.tradefed.device.NullDevice; |
| import com.android.tradefed.device.TestDeviceState; |
| import com.android.tradefed.invoker.IInvocationContext; |
| import com.android.tradefed.invoker.InvocationContext; |
| import com.android.tradefed.metrics.proto.MetricMeasurement.Metric; |
| import com.android.tradefed.result.ByteArrayInputStreamSource; |
| import com.android.tradefed.result.ITestInvocationListener; |
| import com.android.tradefed.result.LogDataType; |
| import com.android.tradefed.result.TestDescription; |
| import com.android.tradefed.util.IRunUtil; |
| |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| |
| import java.util.HashMap; |
| |
| /** Unit tests for {@link LogcatOnFailureCollector}. */ |
| @RunWith(JUnit4.class) |
| public class LogcatOnFailureCollectorTest { |
| private TestableLogcatOnFailureCollector mCollector; |
| @Mock ITestInvocationListener mMockListener; |
| @Mock ITestDevice mMockDevice; |
| @Mock ITestDevice mNullMockDevice; |
| |
| private ITestInvocationListener mTestListener; |
| private IInvocationContext mContext; |
| @Mock ILogcatReceiver mMockReceiver; |
| @Mock IRunUtil mMockRunUtil; |
| |
| private class TestableLogcatOnFailureCollector extends LogcatOnFailureCollector { |
| |
| public boolean mOnTestStartCalled = false; |
| public boolean mOnTestFailCalled = false; |
| |
| @Override |
| public void onTestStart(DeviceMetricData testData) { |
| super.onTestStart(testData); |
| mOnTestStartCalled = true; |
| } |
| |
| @Override |
| public void onTestFail(DeviceMetricData testData, TestDescription test) { |
| super.onTestFail(testData, test); |
| mOnTestFailCalled = true; |
| } |
| |
| @Override |
| ILogcatReceiver createLogcatReceiver(ITestDevice device) { |
| return mMockReceiver; |
| } |
| |
| @Override |
| IRunUtil getRunUtil() { |
| return mMockRunUtil; |
| } |
| } |
| |
| @Before |
| public void setUp() throws Exception { |
| MockitoAnnotations.initMocks(this); |
| |
| mCollector = new TestableLogcatOnFailureCollector(); |
| mContext = new InvocationContext(); |
| mContext.addAllocatedDevice(ConfigurationDef.DEFAULT_DEVICE_NAME, mMockDevice); |
| mContext.addAllocatedDevice("second_null_device", mNullMockDevice); |
| |
| when(mMockDevice.getSerialNumber()).thenReturn("serial"); |
| when(mMockDevice.getIDevice()).thenReturn(mock(IDevice.class)); |
| when(mMockDevice.getDeviceState()).thenReturn(TestDeviceState.ONLINE); |
| |
| when(mNullMockDevice.getIDevice()).thenReturn(new NullDevice("null-dev")); |
| } |
| |
| @Test |
| public void testCollect() throws Exception { |
| when(mMockDevice.getApiLevel()).thenReturn(20); |
| |
| TestDescription test = new TestDescription("class", "test"); |
| |
| // Buffer at testRunStarted |
| when(mMockReceiver.getLogcatData()) |
| .thenReturn(new ByteArrayInputStreamSource("aaa".getBytes())); |
| // Buffer to be logged |
| when(mMockReceiver.getLogcatData(Mockito.anyInt(), Mockito.eq(3))) |
| .thenReturn(new ByteArrayInputStreamSource("aaabbb".getBytes())); |
| |
| mTestListener = mCollector.init(mContext, mMockListener); |
| mTestListener.testRunStarted("runName", 1); |
| mTestListener.testStarted(test); |
| mTestListener.testFailed(test, "I failed"); |
| mTestListener.testEnded(test, new HashMap<String, Metric>()); |
| mTestListener.testRunEnded(0L, new HashMap<String, Metric>()); |
| |
| verify(mMockReceiver).start(); |
| verify(mMockReceiver).clear(); |
| verify(mMockReceiver).stop(); |
| verify(mMockListener) |
| .testRunStarted( |
| Mockito.eq("runName"), Mockito.eq(1), Mockito.eq(0), Mockito.anyLong()); |
| verify(mMockListener).testStarted(Mockito.eq(test), Mockito.anyLong()); |
| verify(mMockListener).testFailed(Mockito.eq(test), (String) Mockito.any()); |
| verify(mMockListener) |
| .testEnded( |
| Mockito.eq(test), |
| Mockito.anyLong(), |
| Mockito.<HashMap<String, Metric>>any()); |
| verify(mMockListener).testRunEnded(0L, new HashMap<String, Metric>()); |
| verify(mMockListener) |
| .testLog( |
| Mockito.eq("class#test-serial-logcat-on-failure"), |
| Mockito.eq(LogDataType.LOGCAT), |
| Mockito.any()); |
| // Ensure the callback went through |
| assertTrue(mCollector.mOnTestStartCalled); |
| assertTrue(mCollector.mOnTestFailCalled); |
| } |
| |
| /** |
| * If the API level support of the device is lower than a threshold we fall back to a different |
| * collection for the logcat. |
| */ |
| @Test |
| public void testCollect_legacy() throws Exception { |
| when(mMockDevice.getApiLevel()).thenReturn(18); |
| |
| TestDescription test = new TestDescription("class", "test"); |
| |
| mTestListener = mCollector.init(mContext, mMockListener); |
| mTestListener.testRunStarted("runName", 1); |
| mTestListener.testStarted(test); |
| mTestListener.testFailed(test, "I failed"); |
| mTestListener.testEnded(test, new HashMap<String, Metric>()); |
| mTestListener.testRunEnded(0L, new HashMap<String, Metric>()); |
| |
| verify(mMockListener) |
| .testRunStarted( |
| Mockito.eq("runName"), Mockito.eq(1), Mockito.eq(0), Mockito.anyLong()); |
| verify(mMockListener).testStarted(Mockito.eq(test), Mockito.anyLong()); |
| verify(mMockListener).testFailed(Mockito.eq(test), (String) Mockito.any()); |
| verify(mMockListener) |
| .testEnded( |
| Mockito.eq(test), |
| Mockito.anyLong(), |
| Mockito.<HashMap<String, Metric>>any()); |
| verify(mMockListener).testRunEnded(0L, new HashMap<String, Metric>()); |
| verify(mMockDevice).executeShellCommand(Mockito.eq("logcat -t 5000"), Mockito.any()); |
| verify(mMockListener) |
| .testLog( |
| Mockito.eq("class#test-serial-logcat-on-failure"), |
| Mockito.eq(LogDataType.LOGCAT), |
| Mockito.any()); |
| // Ensure the callback went through |
| assertTrue(mCollector.mOnTestStartCalled); |
| assertTrue(mCollector.mOnTestFailCalled); |
| } |
| |
| @Test |
| public void testCollect_noRuns() throws Exception { |
| // If there was no runs, nothing should be done. |
| |
| mTestListener = mCollector.init(mContext, mMockListener); |
| |
| assertFalse(mCollector.mOnTestStartCalled); |
| assertFalse(mCollector.mOnTestFailCalled); |
| } |
| |
| @Test |
| public void testCollect_multiRun() throws Exception { |
| when(mMockDevice.getApiLevel()).thenReturn(20); |
| |
| TestDescription test = new TestDescription("class", "test"); |
| TestDescription test2 = new TestDescription("class2", "test2"); |
| |
| // Buffer at testRunStarted |
| when(mMockReceiver.getLogcatData()) |
| .thenReturn(new ByteArrayInputStreamSource("aaa".getBytes())); |
| // Buffer to be logged |
| when(mMockReceiver.getLogcatData(Mockito.anyInt(), Mockito.eq(3))) |
| .thenReturn(new ByteArrayInputStreamSource("aaabbb".getBytes())); |
| |
| // Buffer at testRunStarted |
| when(mMockReceiver.getLogcatData()) |
| .thenReturn(new ByteArrayInputStreamSource("aaa".getBytes())); |
| // Buffer to be logged |
| when(mMockReceiver.getLogcatData(Mockito.anyInt(), Mockito.eq(3))) |
| .thenReturn(new ByteArrayInputStreamSource("aaabbb".getBytes())); |
| |
| mTestListener = mCollector.init(mContext, mMockListener); |
| mTestListener.testRunStarted("runName", 1); |
| mTestListener.testStarted(test); |
| mTestListener.testFailed(test, "I failed"); |
| mTestListener.testEnded(test, new HashMap<String, Metric>()); |
| mTestListener.testRunEnded(0L, new HashMap<String, Metric>()); |
| // Second run |
| mTestListener.testRunStarted("runName2", 1); |
| mTestListener.testStarted(test2); |
| mTestListener.testFailed(test2, "I failed"); |
| mTestListener.testEnded(test2, new HashMap<String, Metric>()); |
| mTestListener.testRunEnded(0L, new HashMap<String, Metric>()); |
| verify(mMockReceiver, times(2)).start(); |
| verify(mMockReceiver, times(2)).clear(); |
| verify(mMockReceiver, times(2)).stop(); |
| verify(mMockListener) |
| .testRunStarted( |
| Mockito.eq("runName"), Mockito.eq(1), Mockito.eq(0), Mockito.anyLong()); |
| verify(mMockListener).testStarted(Mockito.eq(test), Mockito.anyLong()); |
| verify(mMockListener).testFailed(Mockito.eq(test), (String) Mockito.any()); |
| verify(mMockListener) |
| .testEnded( |
| Mockito.eq(test), |
| Mockito.anyLong(), |
| Mockito.<HashMap<String, Metric>>any()); |
| // verify testRunEnded for both runs with times(2) |
| verify(mMockListener, times(2)).testRunEnded(0L, new HashMap<String, Metric>()); |
| verify(mMockListener) |
| .testLog( |
| Mockito.eq("class#test-serial-logcat-on-failure"), |
| Mockito.eq(LogDataType.LOGCAT), |
| Mockito.any()); |
| verify(mMockListener) |
| .testRunStarted( |
| Mockito.eq("runName2"), Mockito.eq(1), Mockito.eq(0), Mockito.anyLong()); |
| verify(mMockListener).testStarted(Mockito.eq(test2), Mockito.anyLong()); |
| verify(mMockListener).testFailed(Mockito.eq(test2), (String) Mockito.any()); |
| verify(mMockListener) |
| .testEnded( |
| Mockito.eq(test2), |
| Mockito.anyLong(), |
| Mockito.<HashMap<String, Metric>>any()); |
| verify(mMockListener) |
| .testLog( |
| Mockito.eq("class2#test2-serial-logcat-on-failure"), |
| Mockito.eq(LogDataType.LOGCAT), |
| Mockito.any()); |
| // Ensure the callback went through |
| assertTrue(mCollector.mOnTestStartCalled); |
| assertTrue(mCollector.mOnTestFailCalled); |
| } |
| } |