blob: d7198c16a78aae2113f600bdecffae1f5016fc54 [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 android.device.collectors;
import static org.junit.Assert.assertEquals;
import static org.mockito.AdditionalMatchers.not;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.endsWith;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.matches;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.app.Instrumentation;
import android.device.collectors.util.SendToInstrumentation;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.test.uiautomator.UiDevice;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.Description;
import org.junit.runner.notification.Failure;
import org.junit.runner.Result;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.io.File;
import java.io.IOException;
import java.util.List;
/**
* Android Unit tests for {@link ScreenRecordCollector}.
*
* <p>To run: atest CollectorDeviceLibTest:android.device.collectors.ScreenRecordCollectorTest
*/
@RunWith(AndroidJUnit4.class)
public class ScreenRecordCollectorTest {
private static final int NUM_TEST_CASE = 10;
private File mLogDir;
private Description mRunDesc;
private Description mTestDesc;
private ScreenRecordCollector mListener;
@Mock private Instrumentation mInstrumentation;
@Mock private UiDevice mDevice;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLogDir = new File("tmp/");
mRunDesc = Description.createSuiteDescription("run");
mTestDesc = Description.createTestDescription("run", "test");
}
@After
public void tearDown() {
if (mLogDir != null) {
mLogDir.delete();
}
}
private ScreenRecordCollector initListener() throws IOException {
ScreenRecordCollector listener = spy(new ScreenRecordCollector());
listener.setInstrumentation(mInstrumentation);
doReturn(mLogDir).when(listener).createAndEmptyDirectory(anyString());
doReturn(0L).when(listener).getTailBuffer();
doReturn(mDevice).when(listener).getDevice();
doReturn("1234").when(mDevice).executeShellCommand(eq("pidof screenrecord"));
doReturn("").when(mDevice).executeShellCommand(not(eq("pidof screenrecord")));
return listener;
}
/**
* Test that screen recording is properly started and ended for each test over the course of a
* test run.
*/
@Test
public void testScreenRecord() throws Exception {
mListener = initListener();
// Verify output directories are created on test run start.
mListener.testRunStarted(mRunDesc);
verify(mListener).createAndEmptyDirectory(ScreenRecordCollector.OUTPUT_DIR);
// Walk through a number of test cases to simulate behavior.
for (int i = 1; i <= NUM_TEST_CASE; i++) {
// Verify a thread is started when the test starts.
mListener.testStarted(mTestDesc);
verify(mListener, times(i)).startScreenRecordThread(anyString());
// Delay verification by 100 ms to ensure the thread was started.
SystemClock.sleep(100);
verify(mDevice, times(i)).executeShellCommand(matches("screenrecord .*"));
// Alternate between pass and fail for variety.
if (i % 2 == 0) {
mListener.testFailure(new Failure(mTestDesc, new RuntimeException("I failed")));
}
// Verify all processes are killed when the test ends.
mListener.testFinished(mTestDesc);
verify(mListener, times(i)).killScreenRecordProcesses();
verify(mDevice, times(i)).executeShellCommand(eq("pidof screenrecord"));
verify(mDevice, times(i)).executeShellCommand(matches("kill -2 1234"));
}
// Verify files are reported
mListener.testRunFinished(new Result());
Bundle resultBundle = new Bundle();
mListener.instrumentationRunFinished(System.out, resultBundle, new Result());
ArgumentCaptor<Bundle> capture = ArgumentCaptor.forClass(Bundle.class);
Mockito.verify(mInstrumentation, times(NUM_TEST_CASE))
.sendStatus(
Mockito.eq(SendToInstrumentation.INST_STATUS_IN_PROGRESS),
capture.capture());
List<Bundle> capturedBundle = capture.getAllValues();
assertEquals(NUM_TEST_CASE, capturedBundle.size());
int videoCount = 0;
for (Bundle bundle : capturedBundle) {
for (String key : bundle.keySet()) {
if (key.contains("mp4")) videoCount++;
}
}
assertEquals(NUM_TEST_CASE, videoCount);
}
/** Test that screen recording is properly done for multiple tests and labels iterations. */
@Test
public void testMultipleScreenRecords() throws Exception {
mListener = initListener();
// Run through a sequence of `NUM_TEST_CASE` failing tests.
mListener.testRunStarted(mRunDesc);
verify(mListener).createAndEmptyDirectory(ScreenRecordCollector.OUTPUT_DIR);
// Walk through a number of test cases to simulate behavior.
for (int i = 1; i <= NUM_TEST_CASE; i++) {
mListener.testStarted(mTestDesc);
mListener.testFinished(mTestDesc);
}
mListener.testRunFinished(new Result());
// Verify that videos are saved with iterations.
InOrder videoVerifier = inOrder(mListener);
// The first video should not have an iteration number.
videoVerifier.verify(mListener).startScreenRecordThread(matches("^.*[^1].mp4$"));
// The subsequent videos should have an iteration number.
for (int i = 1; i < NUM_TEST_CASE; i++) {
videoVerifier
.verify(mListener)
.startScreenRecordThread(endsWith(String.format("%d-video.mp4", i + 1)));
}
}
}