/*
 * Copyright (C) 2010 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.invoker;

import static org.mockito.Mockito.doReturn;

import com.android.ddmlib.IDevice;
import com.android.tradefed.build.BuildInfo;
import com.android.tradefed.build.BuildRetrievalError;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.build.IBuildInfo.BuildInfoProperties;
import com.android.tradefed.build.IBuildProvider;
import com.android.tradefed.build.IDeviceBuildInfo;
import com.android.tradefed.build.IDeviceBuildInfo.ExternalLinkedDir;
import com.android.tradefed.build.IDeviceBuildProvider;
import com.android.tradefed.command.CommandOptions;
import com.android.tradefed.command.CommandRunner.ExitCode;
import com.android.tradefed.command.FatalHostError;
import com.android.tradefed.command.ICommandOptions;
import com.android.tradefed.command.remote.DeviceDescriptor;
import com.android.tradefed.config.Configuration;
import com.android.tradefed.config.ConfigurationDef;
import com.android.tradefed.config.DeviceConfigurationHolder;
import com.android.tradefed.config.IConfiguration;
import com.android.tradefed.config.IConfigurationFactory;
import com.android.tradefed.config.IDeviceConfiguration;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.OptionSetter;
import com.android.tradefed.device.DeviceAllocationState;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.IDeviceRecovery;
import com.android.tradefed.device.INativeDevice;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.device.ITestDevice.RecoveryMode;
import com.android.tradefed.device.StubDevice;
import com.android.tradefed.device.TestDeviceOptions;
import com.android.tradefed.device.metric.BaseDeviceMetricCollector;
import com.android.tradefed.device.metric.DeviceMetricData;
import com.android.tradefed.device.metric.IMetricCollector;
import com.android.tradefed.guice.InvocationScope;
import com.android.tradefed.invoker.shard.IShardHelper;
import com.android.tradefed.invoker.shard.ShardHelper;
import com.android.tradefed.invoker.shard.StrictShardHelper;
import com.android.tradefed.log.ILeveledLogOutput;
import com.android.tradefed.log.ILogRegistry;
import com.android.tradefed.metrics.proto.MetricMeasurement.Measurements;
import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
import com.android.tradefed.result.ByteArrayInputStreamSource;
import com.android.tradefed.result.ILogSaver;
import com.android.tradefed.result.ILogSaverListener;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.ITestSummaryListener;
import com.android.tradefed.result.InputStreamSource;
import com.android.tradefed.result.InvocationStatus;
import com.android.tradefed.result.LogDataType;
import com.android.tradefed.result.LogFile;
import com.android.tradefed.result.TestDescription;
import com.android.tradefed.result.TestSummary;
import com.android.tradefed.targetprep.BuildError;
import com.android.tradefed.targetprep.ITargetCleaner;
import com.android.tradefed.targetprep.ITargetPreparer;
import com.android.tradefed.testtype.IDeviceTest;
import com.android.tradefed.testtype.IInvocationContextReceiver;
import com.android.tradefed.testtype.IRemoteTest;
import com.android.tradefed.testtype.IResumableTest;
import com.android.tradefed.testtype.IRetriableTest;
import com.android.tradefed.testtype.IShardableTest;
import com.android.tradefed.testtype.IStrictShardableTest;
import com.android.tradefed.testtype.StubTest;
import com.android.tradefed.util.FileUtil;
import com.android.tradefed.util.SystemUtil.EnvVariable;

import com.google.common.util.concurrent.SettableFuture;

import junit.framework.Test;
import junit.framework.TestCase;

import org.easymock.Capture;
import org.easymock.EasyMock;
import org.mockito.Mockito;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/** Unit tests for {@link TestInvocation}. */
@SuppressWarnings("MustBeClosedChecker")
public class TestInvocationTest extends TestCase {

    private static final String SERIAL = "serial";
    private static final Map<String, String> EMPTY_MAP = Collections.emptyMap();
    private static final String PATH = "path";
    private static final String URL = "url";
    private static final TestSummary mSummary = new TestSummary("http://www.url.com/report.txt");
    private static final InputStreamSource EMPTY_STREAM_SOURCE =
            new ByteArrayInputStreamSource(new byte[0]);
    private static final String LOGCAT_NAME_ERROR =
            TestInvocation.getDeviceLogName(TestInvocation.Stage.ERROR);
    private static final String LOGCAT_NAME_SETUP =
            TestInvocation.getDeviceLogName(TestInvocation.Stage.SETUP);
    private static final String LOGCAT_NAME_TEST =
            TestInvocation.getDeviceLogName(TestInvocation.Stage.TEST);
    private static final String LOGCAT_NAME_TEARDOWN =
            TestInvocation.getDeviceLogName(TestInvocation.Stage.TEARDOWN);
    /** The {@link TestInvocation} under test, with all dependencies mocked out */
    private TestInvocation mTestInvocation;

    private IConfiguration mStubConfiguration;
    private IConfiguration mStubMultiConfiguration;

    private IInvocationContext mStubInvocationMetadata;

    // The mock objects.
    private ITestDevice mMockDevice;
    private ITargetPreparer mMockPreparer;
    private IBuildProvider mMockBuildProvider;
    private IBuildInfo mMockBuildInfo;
    private ITestInvocationListener mMockTestListener;
    private ITestSummaryListener mMockSummaryListener;
    private ILeveledLogOutput mMockLogger;
    private ILogSaver mMockLogSaver;
    private IDeviceRecovery mMockRecovery;
    private Capture<List<TestSummary>> mUriCapture;
    private ILogRegistry mMockLogRegistry;
    private IConfigurationFactory mMockConfigFactory;
    private IRescheduler mockRescheduler;
    private DeviceDescriptor mFakeDescriptor;

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        mStubConfiguration = new Configuration("foo", "bar");
        mStubMultiConfiguration = new Configuration("foo", "bar");

        mMockDevice = EasyMock.createMock(ITestDevice.class);
        mMockRecovery = EasyMock.createMock(IDeviceRecovery.class);
        mMockPreparer = EasyMock.createMock(ITargetPreparer.class);
        mMockBuildProvider = EasyMock.createMock(IBuildProvider.class);

        // Use strict mocks here since the order of Listener calls is important
        mMockTestListener = EasyMock.createStrictMock(ITestInvocationListener.class);
        mMockSummaryListener = EasyMock.createStrictMock(ITestSummaryListener.class);
        mMockBuildInfo = EasyMock.createMock(IBuildInfo.class);
        mMockLogger = EasyMock.createMock(ILeveledLogOutput.class);
        mMockLogRegistry = EasyMock.createMock(ILogRegistry.class);
        mMockLogSaver = EasyMock.createMock(ILogSaver.class);
        mMockConfigFactory = EasyMock.createMock(IConfigurationFactory.class);
        mockRescheduler = EasyMock.createMock(IRescheduler.class);

        mStubConfiguration.setDeviceRecovery(mMockRecovery);
        mStubConfiguration.setTargetPreparer(mMockPreparer);
        mStubConfiguration.setBuildProvider(mMockBuildProvider);

        EasyMock.expect(mMockPreparer.isDisabled()).andStubReturn(false);
        EasyMock.expect(mMockPreparer.isTearDownDisabled()).andStubReturn(false);

        List<IDeviceConfiguration> deviceConfigs = new ArrayList<IDeviceConfiguration>();
        IDeviceConfiguration device1 =
                new DeviceConfigurationHolder(ConfigurationDef.DEFAULT_DEVICE_NAME);
        device1.addSpecificConfig(mMockRecovery);
        device1.addSpecificConfig(mMockPreparer);
        device1.addSpecificConfig(mMockBuildProvider);
        deviceConfigs.add(device1);
        mStubMultiConfiguration.setDeviceConfigList(deviceConfigs);

        mStubConfiguration.setLogSaver(mMockLogSaver);
        mStubMultiConfiguration.setLogSaver(mMockLogSaver);

        List<ITestInvocationListener> listenerList = new ArrayList<ITestInvocationListener>(1);
        listenerList.add(mMockTestListener);
        listenerList.add(mMockSummaryListener);
        mStubConfiguration.setTestInvocationListeners(listenerList);
        mStubMultiConfiguration.setTestInvocationListeners(listenerList);

        mStubConfiguration.setLogOutput(mMockLogger);
        mStubMultiConfiguration.setLogOutput(mMockLogger);
        EasyMock.expect(mMockDevice.getSerialNumber()).andStubReturn(SERIAL);
        EasyMock.expect(mMockDevice.getIDevice()).andStubReturn(null);
        mMockDevice.setRecovery(mMockRecovery);
        mMockDevice.preInvocationSetup((IBuildInfo)EasyMock.anyObject());
        EasyMock.expectLastCall().anyTimes();
        mMockDevice.postInvocationTearDown();
        EasyMock.expectLastCall().anyTimes();
        mFakeDescriptor = new DeviceDescriptor(SERIAL, false, DeviceAllocationState.Available,
                "unknown", "unknown", "unknown", "unknown", "unknown");
        EasyMock.expect(mMockDevice.getDeviceDescriptor()).andStubReturn(mFakeDescriptor);

        EasyMock.expect(mMockBuildInfo.getBuildId()).andStubReturn("1");
        EasyMock.expect(mMockBuildInfo.getBuildAttributes()).andStubReturn(EMPTY_MAP);
        EasyMock.expect(mMockBuildInfo.getBuildBranch()).andStubReturn("branch");
        EasyMock.expect(mMockBuildInfo.getBuildFlavor()).andStubReturn("flavor");
        EasyMock.expect(mMockBuildInfo.getProperties()).andStubReturn(new HashSet<>());

        // always expect logger initialization and cleanup calls
        mMockLogRegistry.registerLogger(mMockLogger);
        mMockLogger.init();
        mMockLogger.closeLog();
        mMockLogRegistry.unregisterLogger();
        mUriCapture = new Capture<List<TestSummary>>();

        mStubInvocationMetadata = new InvocationContext();
        mStubInvocationMetadata.addAllocatedDevice(ConfigurationDef.DEFAULT_DEVICE_NAME,
                mMockDevice);
        mStubInvocationMetadata.addDeviceBuildInfo(ConfigurationDef.DEFAULT_DEVICE_NAME,
                mMockBuildInfo);

        // create the BaseTestInvocation to test
        mTestInvocation =
                new TestInvocation() {
                    @Override
                    ILogRegistry getLogRegistry() {
                        return mMockLogRegistry;
                    }

                    @Override
                    public IInvocationExecution createInvocationExec(boolean isSandboxed) {
                        return new InvocationExecution() {
                            @Override
                            protected IShardHelper createShardHelper() {
                                return new ShardHelper();
                            }
                        };
                    }

                    @Override
                    protected void setExitCode(ExitCode code, Throwable stack) {
                        // empty on purpose
                    }

                    @Override
                    InvocationScope getInvocationScope() {
                        // Avoid re-entry in the current TF invocation scope for unit tests.
                        return new InvocationScope();
                    }
                };
    }

    @Override
    protected void tearDown() throws Exception {
      super.tearDown();

    }

    /**
     * Test the normal case invoke scenario with a {@link IRemoteTest}.
     * <p/>
     * Verifies that all external interfaces get notified as expected.
     */
    public void testInvoke_RemoteTest() throws Throwable {
        IRemoteTest test = EasyMock.createMock(IRemoteTest.class);
        setupMockSuccessListeners();

        test.run((ITestInvocationListener)EasyMock.anyObject());
        setupNormalInvoke(test);
        EasyMock.replay(mockRescheduler);
        mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
        verifyMocks(test, mockRescheduler);
        verifySummaryListener();
    }

    /**
     * Test the normal case for multi invoke scenario with a {@link IRemoteTest}.
     * <p/>
     * Verifies that all external interfaces get notified as expected.
     */
    public void testInvokeMulti_RemoteTest() throws Throwable {
        IRemoteTest test = EasyMock.createMock(IRemoteTest.class);
        setupMockSuccessListeners();

        test.run((ITestInvocationListener)EasyMock.anyObject());
        setupNormalInvoke(test);
        EasyMock.replay(mockRescheduler);
        mTestInvocation.invoke(mStubInvocationMetadata, mStubMultiConfiguration, mockRescheduler);
        verifyMocks(test, mockRescheduler);
        verifySummaryListener();
    }

    /**
     * Test the normal case invoke scenario with an {@link ITestSummaryListener} masquerading as
     * an {@link ITestInvocationListener}.
     * <p/>
     * Verifies that all external interfaces get notified as expected.
     */
    public void testInvoke_twoSummary() throws Throwable {

        IRemoteTest test = EasyMock.createMock(IRemoteTest.class);
        setupMockSuccessListeners();

        test.run((ITestInvocationListener)EasyMock.anyObject());
        setupNormalInvoke(test);
        EasyMock.replay(mockRescheduler);
        mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
        verifyMocks(test, mockRescheduler);
        verifySummaryListener();
    }

    /**
     * Test the invoke scenario where build retrieve fails.
     * <p/>
     * An invocation will be started in this scenario.
     */
    public void testInvoke_buildFailed() throws Throwable  {
        BuildRetrievalError exception = new BuildRetrievalError("error", null, mMockBuildInfo);
        EasyMock.expect(mMockBuildProvider.getBuild()).andThrow(exception);
        EasyMock.expect(mMockBuildInfo.getTestTag()).andStubReturn(null);
        setupMockFailureListeners(exception);
        setupInvoke();
        IRemoteTest test = EasyMock.createMock(IRemoteTest.class);
        CommandOptions cmdOptions = new CommandOptions();
        final String expectedTestTag = "TEST_TAG";
        cmdOptions.setTestTag(expectedTestTag);
        mStubConfiguration.setCommandOptions(cmdOptions);
        mStubConfiguration.setTest(test);
        EasyMock.expect(mMockLogger.getLog()).andReturn(EMPTY_STREAM_SOURCE);
        EasyMock.expect(mMockDevice.getLogcat()).andReturn(EMPTY_STREAM_SOURCE).times(2);
        mMockDevice.clearLogcat();
        EasyMock.expectLastCall().times(2);
        mMockLogRegistry.unregisterLogger();
        mMockLogRegistry.dumpToGlobalLog(mMockLogger);
        mMockLogger.closeLog();
        mMockBuildProvider.cleanUp(mMockBuildInfo);
        replayMocks(test, mockRescheduler);
        mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
        verifyMocks(test, mockRescheduler);
        // invocation test tag was updated.
        assertEquals(expectedTestTag, mStubInvocationMetadata.getTestTag());
    }

    /**
     * Test the invoke scenario where there is no build to test.
     */
    public void testInvoke_noBuild() throws Throwable  {
        EasyMock.expect(mMockBuildProvider.getBuild()).andReturn(null);
        IRemoteTest test = EasyMock.createMock(IRemoteTest.class);
        mStubConfiguration.setTest(test);
        mMockBuildProvider.cleanUp(mMockBuildInfo);
        mMockLogRegistry.dumpToGlobalLog(mMockLogger);
        setupInvoke();
        replayMocks(test, mockRescheduler);
        mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
        verifyMocks(test);
    }

    /**
     * Test the invoke scenario where there is no build to test for a {@link IRetriableTest}.
     */
    public void testInvoke_noBuildRetry() throws Throwable  {
        EasyMock.expect(mMockBuildProvider.getBuild()).andReturn(null);

        IRetriableTest test = EasyMock.createMock(IRetriableTest.class);
        EasyMock.expect(test.isRetriable()).andReturn(Boolean.TRUE);

        EasyMock.expect(mockRescheduler.rescheduleCommand()).andReturn(EasyMock.anyBoolean());

        mStubConfiguration.setTest(test);
        mStubConfiguration.getCommandOptions().setLoopMode(false);
        mMockLogRegistry.dumpToGlobalLog(mMockLogger);
        EasyMock.expectLastCall().times(1);
        setupInvoke();
        mMockBuildProvider.cleanUp(mMockBuildInfo);
        replayMocks(test);
        EasyMock.replay(mockRescheduler);
        mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
        EasyMock.verify(mockRescheduler);
        verifyMocks(test);
    }

    /**
     * Test the{@link TestInvocation#invoke(IInvocationContext, IConfiguration, IRescheduler,
     * ITestInvocationListener[])} scenario
     * where the test is a {@link IDeviceTest}
     */
    public void testInvoke_deviceTest() throws Throwable {
         DeviceConfigTest mockDeviceTest = EasyMock.createMock(DeviceConfigTest.class);
         mStubConfiguration.setTest(mockDeviceTest);
         mockDeviceTest.setDevice(mMockDevice);
         mockDeviceTest.run((ITestInvocationListener)EasyMock.anyObject());
         setupMockSuccessListeners();
         setupNormalInvoke(mockDeviceTest);
         EasyMock.replay(mockRescheduler);
         mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
         verifyMocks(mockDeviceTest, mockRescheduler);
         verifySummaryListener();
    }

    /**
     * Test the invoke scenario where test run throws {@link IllegalArgumentException}
     *
     * @throws Exception if unexpected error occurs
     */
    public void testInvoke_testFail() throws Throwable {
        IllegalArgumentException exception = new IllegalArgumentException();
        IRemoteTest test = EasyMock.createMock(IRemoteTest.class);
        test.run((ITestInvocationListener)EasyMock.anyObject());
        EasyMock.expectLastCall().andThrow(exception);
        setupMockFailureListeners(exception);
        mMockBuildProvider.buildNotTested(mMockBuildInfo);
        setupNormalInvoke(test);
        EasyMock.replay(mockRescheduler);
        try {
            mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
            fail("IllegalArgumentException was not rethrown");
        } catch (IllegalArgumentException e) {
            // expected
        }
        verifyMocks(test, mockRescheduler);
        verifySummaryListener();
    }

    /**
     * Test the invoke scenario where test run throws {@link FatalHostError}
     *
     * @throws Exception if unexpected error occurs
     */
    public void testInvoke_fatalError() throws Throwable {
        FatalHostError exception = new FatalHostError("error");
        IRemoteTest test = EasyMock.createMock(IRemoteTest.class);
        test.run((ITestInvocationListener)EasyMock.anyObject());
        EasyMock.expectLastCall().andThrow(exception);
        setupMockFailureListeners(exception);
        mMockBuildProvider.buildNotTested(mMockBuildInfo);
        setupNormalInvoke(test);
        EasyMock.replay(mockRescheduler);
        try {
            mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
            fail("FatalHostError was not rethrown");
        } catch (FatalHostError e)  {
            // expected
        }
        verifyMocks(test, mockRescheduler);
        verifySummaryListener();
    }

    /**
     * Test the invoke scenario where test run throws {@link DeviceNotAvailableException}
     *
     * @throws Exception if unexpected error occurs
     */
    public void testInvoke_deviceNotAvail() throws Throwable {
        DeviceNotAvailableException exception = new DeviceNotAvailableException("ERROR", SERIAL);
        IRemoteTest test = EasyMock.createMock(IRemoteTest.class);
        test.run((ITestInvocationListener)EasyMock.anyObject());
        EasyMock.expectLastCall().andThrow(exception);
        mMockDevice.setRecoveryMode(RecoveryMode.NONE);
        EasyMock.expectLastCall();
        setupMockFailureListeners(exception);
        mMockBuildProvider.buildNotTested(mMockBuildInfo);
        setupNormalInvoke(test);
        EasyMock.replay(mockRescheduler);
        try {
            mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
            fail("DeviceNotAvailableException not thrown");
        } catch (DeviceNotAvailableException e) {
            // expected
        }
        verifyMocks(test, mockRescheduler);
        verifySummaryListener();
    }

    /**
     * Test the invoke scenario where preparer throws {@link BuildError}
     *
     * @throws Exception if unexpected error occurs
     */
    public void testInvoke_buildError() throws Throwable {
        BuildError exception = new BuildError("error", mFakeDescriptor);
        IRemoteTest test = EasyMock.createMock(IRemoteTest.class);
        mStubConfiguration.setTest(test);
        EasyMock.expect(mMockBuildProvider.getBuild()).andReturn(mMockBuildInfo);

        mMockPreparer.setUp(mMockDevice, mMockBuildInfo);
        EasyMock.expectLastCall().andThrow(exception);
        setupMockFailureListeners(exception);
        EasyMock.expect(mMockDevice.getBugreport()).andReturn(EMPTY_STREAM_SOURCE);
        setupInvokeWithBuild();
        replayMocks(test);
        EasyMock.replay(mockRescheduler);
        mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
        verifyMocks(test, mockRescheduler);
        verifySummaryListener();
    }

    /**
     * Test the invoke scenario for a {@link IResumableTest}.
     *
     * @throws Exception if unexpected error occurs
     */
    public void testInvoke_resume() throws Throwable {
        IResumableTest resumableTest = EasyMock.createMock(IResumableTest.class);
        mStubConfiguration.setTest(resumableTest);
        ITestInvocationListener resumeListener = EasyMock.createStrictMock(
                ITestInvocationListener.class);
        mStubConfiguration.setTestInvocationListener(resumeListener);

        EasyMock.expect(mMockBuildProvider.getBuild()).andReturn(mMockBuildInfo);
        resumeListener.invocationStarted(mStubInvocationMetadata);
        mMockDevice.clearLastConnectedWifiNetwork();
        mMockDevice.setOptions((TestDeviceOptions)EasyMock.anyObject());
        mMockBuildInfo.setDeviceSerial(SERIAL);
        EasyMock.expect(mMockBuildInfo.getTestTag()).andStubReturn("");
        mMockDevice.startLogcat();
        mMockPreparer.setUp(mMockDevice, mMockBuildInfo);

        resumableTest.run((ITestInvocationListener) EasyMock.anyObject());
        EasyMock.expectLastCall().andThrow(new DeviceNotAvailableException("ERROR", SERIAL));
        EasyMock.expect(resumableTest.isResumable()).andReturn(Boolean.TRUE);
        mMockDevice.setRecoveryMode(RecoveryMode.NONE);
        EasyMock.expectLastCall();
        EasyMock.expect(mMockDevice.getLogcat()).andReturn(EMPTY_STREAM_SOURCE).times(3);
        mMockDevice.clearLogcat();
        EasyMock.expectLastCall().times(3);
        EasyMock.expect(mMockLogger.getLog()).andReturn(EMPTY_STREAM_SOURCE);
        EasyMock.expect(
                        mMockLogSaver.saveLogData(
                                EasyMock.eq(LOGCAT_NAME_SETUP),
                                EasyMock.eq(LogDataType.LOGCAT),
                                (InputStream) EasyMock.anyObject()))
                .andReturn(new LogFile(PATH, URL, LogDataType.TEXT));
        EasyMock.expect(
                        mMockLogSaver.saveLogData(
                                EasyMock.eq(LOGCAT_NAME_TEST),
                                EasyMock.eq(LogDataType.LOGCAT),
                                (InputStream) EasyMock.anyObject()))
                .andReturn(new LogFile(PATH, URL, LogDataType.TEXT));
        EasyMock.expect(
                        mMockLogSaver.saveLogData(
                                EasyMock.eq(LOGCAT_NAME_TEARDOWN),
                                EasyMock.eq(LogDataType.LOGCAT),
                                (InputStream) EasyMock.anyObject()))
                .andReturn(new LogFile(PATH, URL, LogDataType.TEXT));
        EasyMock.expect(
                        mMockLogSaver.saveLogData(
                                EasyMock.eq(TestInvocation.TRADEFED_LOG_NAME),
                                EasyMock.eq(LogDataType.TEXT),
                                (InputStream) EasyMock.anyObject()))
                .andReturn(new LogFile(PATH, URL, LogDataType.TEXT));
        resumeListener.testLog(
                EasyMock.eq(LOGCAT_NAME_SETUP),
                EasyMock.eq(LogDataType.LOGCAT),
                (InputStreamSource) EasyMock.anyObject());
        resumeListener.testLog(
                EasyMock.eq(LOGCAT_NAME_TEST),
                EasyMock.eq(LogDataType.LOGCAT),
                (InputStreamSource) EasyMock.anyObject());
        resumeListener.testLog(
                EasyMock.eq(LOGCAT_NAME_TEARDOWN),
                EasyMock.eq(LogDataType.LOGCAT),
                (InputStreamSource) EasyMock.anyObject());
        resumeListener.testLog(EasyMock.eq(TestInvocation.TRADEFED_LOG_NAME),
                EasyMock.eq(LogDataType.TEXT), (InputStreamSource)EasyMock.anyObject());

        // just return same build and logger for simplicity
        EasyMock.expect(mMockBuildInfo.clone()).andReturn(mMockBuildInfo);
        EasyMock.expect(mMockLogger.clone()).andReturn(mMockLogger);
        IRescheduler mockRescheduler = EasyMock.createMock(IRescheduler.class);
        Capture<IConfiguration> capturedConfig = new Capture<IConfiguration>();
        EasyMock.expect(mockRescheduler.scheduleConfig(EasyMock.capture(capturedConfig)))
                .andReturn(Boolean.TRUE);
        // When resuming the original build provider is still going to handle the clean up.
        mMockBuildProvider.cleanUp(mMockBuildInfo);
        EasyMock.expectLastCall().times(4);
        mMockDevice.clearLastConnectedWifiNetwork();
        mMockDevice.stopLogcat();

        mMockLogger.init();
        mMockLogSaver.invocationStarted(mStubInvocationMetadata);
        // now set resumed invocation expectations
        mMockDevice.clearLastConnectedWifiNetwork();
        mMockDevice.setOptions((TestDeviceOptions)EasyMock.anyObject());
        mMockBuildInfo.setDeviceSerial(SERIAL);
        mMockBuildInfo.setTestTag(EasyMock.eq("stub"));
        EasyMock.expectLastCall().times(2);
        mMockDevice.startLogcat();
        mMockPreparer.setUp(mMockDevice, mMockBuildInfo);
        mMockLogSaver.invocationStarted(mStubInvocationMetadata);
        mMockDevice.setRecovery(mMockRecovery);
        resumableTest.run((ITestInvocationListener)EasyMock.anyObject());
        EasyMock.expect(mMockDevice.getLogcat()).andReturn(EMPTY_STREAM_SOURCE).times(3);
        mMockDevice.clearLogcat();
        EasyMock.expectLastCall().times(3);
        EasyMock.expect(mMockLogger.getLog()).andReturn(EMPTY_STREAM_SOURCE);
        EasyMock.expect(
                        mMockLogSaver.saveLogData(
                                EasyMock.eq(LOGCAT_NAME_SETUP),
                                EasyMock.eq(LogDataType.LOGCAT),
                                (InputStream) EasyMock.anyObject()))
                .andReturn(new LogFile(PATH, URL, LogDataType.TEXT));
        EasyMock.expect(
                        mMockLogSaver.saveLogData(
                                EasyMock.eq(LOGCAT_NAME_TEST),
                                EasyMock.eq(LogDataType.LOGCAT),
                                (InputStream) EasyMock.anyObject()))
                .andReturn(new LogFile(PATH, URL, LogDataType.TEXT));
        EasyMock.expect(
                        mMockLogSaver.saveLogData(
                                EasyMock.eq(LOGCAT_NAME_TEARDOWN),
                                EasyMock.eq(LogDataType.LOGCAT),
                                (InputStream) EasyMock.anyObject()))
                .andReturn(new LogFile(PATH, URL, LogDataType.TEXT));
        EasyMock.expect(
                        mMockLogSaver.saveLogData(
                                EasyMock.eq(TestInvocation.TRADEFED_LOG_NAME),
                                EasyMock.eq(LogDataType.TEXT),
                                (InputStream) EasyMock.anyObject()))
                .andReturn(new LogFile(PATH, URL, LogDataType.TEXT));
        resumeListener.testLog(
                EasyMock.eq(LOGCAT_NAME_SETUP),
                EasyMock.eq(LogDataType.LOGCAT),
                (InputStreamSource) EasyMock.anyObject());
        resumeListener.testLog(
                EasyMock.eq(LOGCAT_NAME_TEST),
                EasyMock.eq(LogDataType.LOGCAT),
                (InputStreamSource) EasyMock.anyObject());
        resumeListener.testLog(
                EasyMock.eq(LOGCAT_NAME_TEARDOWN),
                EasyMock.eq(LogDataType.LOGCAT),
                (InputStreamSource) EasyMock.anyObject());
        resumeListener.testLog(
                EasyMock.eq(TestInvocation.TRADEFED_LOG_NAME),
                EasyMock.eq(LogDataType.TEXT),
                (InputStreamSource) EasyMock.anyObject());
        resumeListener.invocationEnded(EasyMock.anyLong());
        mMockLogSaver.invocationEnded(EasyMock.anyLong());
        EasyMock.expect(resumeListener.getSummary()).andReturn(null);
        mMockLogger.closeLog();
        EasyMock.expectLastCall().times(3);
        mMockDevice.clearLastConnectedWifiNetwork();
        mMockDevice.stopLogcat();
        EasyMock.replay(mockRescheduler, resumeListener, resumableTest, mMockPreparer,
                mMockBuildProvider, mMockLogger, mMockLogSaver, mMockDevice, mMockBuildInfo);

        try {
            mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
            fail("DeviceNotAvailableException not thrown");
        } catch (DeviceNotAvailableException e) {
            // expect
        }
        // now call again, and expect invocation to be resumed properly
        mTestInvocation.invoke(mStubInvocationMetadata, capturedConfig.getValue(), mockRescheduler);

        EasyMock.verify(mockRescheduler, resumeListener, resumableTest, mMockPreparer,
                mMockBuildProvider, mMockLogger, mMockLogSaver, mMockDevice, mMockBuildInfo);
    }

    /**
     * Test the invoke scenario for a {@link IRetriableTest}.
     *
     * @throws Exception if unexpected error occurs
     */
    public void testInvoke_retry() throws Throwable {
        AssertionError exception = new AssertionError();
        IRetriableTest test = EasyMock.createMock(IRetriableTest.class);
        test.run((ITestInvocationListener)EasyMock.anyObject());
        EasyMock.expectLastCall().andThrow(exception);
        EasyMock.expect(test.isRetriable()).andReturn(Boolean.TRUE);
        mStubConfiguration.getCommandOptions().setLoopMode(false);
        IRescheduler mockRescheduler = EasyMock.createMock(IRescheduler.class);
        EasyMock.expect(mockRescheduler.rescheduleCommand()).andReturn(EasyMock.anyBoolean());
        mMockBuildProvider.buildNotTested(mMockBuildInfo);
        setupMockFailureListeners(exception);
        setupNormalInvoke(test);
        EasyMock.replay(mockRescheduler);
        mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
        verifyMocks(test, mockRescheduler);
        verifySummaryListener();
    }

    /**
     * Test the {@link TestInvocation#invoke(IInvocationContext, IConfiguration, IRescheduler,
     * ITestInvocationListener[])} scenario
     * when a {@link ITargetCleaner} is part of the config.
     */
    public void testInvoke_tearDown() throws Throwable {
         IRemoteTest test = EasyMock.createNiceMock(IRemoteTest.class);
         ITargetCleaner mockCleaner = EasyMock.createMock(ITargetCleaner.class);
        EasyMock.expect(mockCleaner.isDisabled()).andReturn(false).times(2);
        EasyMock.expect(mockCleaner.isTearDownDisabled()).andReturn(false);
         mockCleaner.setUp(mMockDevice, mMockBuildInfo);
         mockCleaner.tearDown(mMockDevice, mMockBuildInfo, null);
         mStubConfiguration.getTargetPreparers().add(mockCleaner);
         setupMockSuccessListeners();
         setupNormalInvoke(test);
         EasyMock.replay(mockCleaner, mockRescheduler);
         mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
         verifyMocks(mockCleaner, mockRescheduler);
         verifySummaryListener();
    }

    /**
     * Test the {@link TestInvocation#invoke(IInvocationContext, IConfiguration, IRescheduler,
     * ITestInvocationListener[])} scenario
     * when a {@link ITargetCleaner} is part of the config, and the test throws a
     * {@link DeviceNotAvailableException}.
     */
    public void testInvoke_tearDown_deviceNotAvail() throws Throwable {
        DeviceNotAvailableException exception = new DeviceNotAvailableException("ERROR", SERIAL);
        IRemoteTest test = EasyMock.createMock(IRemoteTest.class);
        test.run((ITestInvocationListener)EasyMock.anyObject());
        EasyMock.expectLastCall().andThrow(exception);
        ITargetCleaner mockCleaner = EasyMock.createMock(ITargetCleaner.class);
        EasyMock.expect(mockCleaner.isDisabled()).andReturn(false).times(2);
        EasyMock.expect(mockCleaner.isTearDownDisabled()).andReturn(false);
        mockCleaner.setUp(mMockDevice, mMockBuildInfo);
        EasyMock.expectLastCall();
        mockCleaner.tearDown(mMockDevice, mMockBuildInfo, exception);
        EasyMock.expectLastCall();
        mMockDevice.setRecoveryMode(RecoveryMode.NONE);
        EasyMock.expectLastCall();
        EasyMock.replay(mockCleaner, mockRescheduler);
        mStubConfiguration.getTargetPreparers().add(mockCleaner);
        setupMockFailureListeners(exception);
        mMockBuildProvider.buildNotTested(mMockBuildInfo);
        setupNormalInvoke(test);
        try {
            mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
            fail("DeviceNotAvailableException not thrown");
        } catch (DeviceNotAvailableException e) {
            // expected
        }
        verifyMocks(mockCleaner, mockRescheduler);
        verifySummaryListener();
    }

    /**
     * Test the {@link TestInvocation#invoke(IInvocationContext, IConfiguration, IRescheduler,
     * ITestInvocationListener[])} scenario
     * when a {@link ITargetCleaner} is part of the config, and the test throws a
     * {@link RuntimeException}.
     */
    public void testInvoke_tearDown_runtime() throws Throwable {
        RuntimeException exception = new RuntimeException();
        IRemoteTest test = EasyMock.createMock(IRemoteTest.class);
        test.run((ITestInvocationListener)EasyMock.anyObject());
        EasyMock.expectLastCall().andThrow(exception);
        ITargetCleaner mockCleaner = EasyMock.createMock(ITargetCleaner.class);
        EasyMock.expect(mockCleaner.isDisabled()).andReturn(false).times(2);
        EasyMock.expect(mockCleaner.isTearDownDisabled()).andReturn(false);
        mockCleaner.setUp(mMockDevice, mMockBuildInfo);
        // tearDown should be called
        mockCleaner.tearDown(mMockDevice, mMockBuildInfo, exception);
        mStubConfiguration.getTargetPreparers().add(mockCleaner);
        setupMockFailureListeners(exception);
        mMockBuildProvider.buildNotTested(mMockBuildInfo);
        setupNormalInvoke(test);
        EasyMock.replay(mockCleaner, mockRescheduler);
        try {
            mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
            fail("RuntimeException not thrown");
        } catch (RuntimeException e) {
            // expected
        }
        verifyMocks(mockCleaner, mockRescheduler);
        verifySummaryListener();
    }

    /**
     * Test the {@link TestInvocation#invoke(IInvocationContext, IConfiguration, IRescheduler,
     * ITestInvocationListener[])} scenario
     * when there is {@link ITestInvocationListener} which implements the {@link ILogSaverListener}
     * interface.
     */
    public void testInvoke_logFileSaved() throws Throwable {
        List<ITestInvocationListener> listenerList =
                mStubConfiguration.getTestInvocationListeners();
        ILogSaverListener logSaverListener = EasyMock.createMock(ILogSaverListener.class);
        listenerList.add(logSaverListener);
        mStubConfiguration.setTestInvocationListeners(listenerList);

        logSaverListener.setLogSaver(mMockLogSaver);
        logSaverListener.invocationStarted(mStubInvocationMetadata);
        logSaverListener.testLog(
                EasyMock.eq(LOGCAT_NAME_SETUP),
                EasyMock.eq(LogDataType.LOGCAT),
                (InputStreamSource) EasyMock.anyObject());
        logSaverListener.testLogSaved(
                EasyMock.eq(LOGCAT_NAME_SETUP),
                EasyMock.eq(LogDataType.LOGCAT),
                (InputStreamSource) EasyMock.anyObject(),
                (LogFile) EasyMock.anyObject());
        logSaverListener.logAssociation(EasyMock.eq(LOGCAT_NAME_SETUP), EasyMock.anyObject());
        logSaverListener.testLog(
                EasyMock.eq(LOGCAT_NAME_TEST),
                EasyMock.eq(LogDataType.LOGCAT),
                (InputStreamSource) EasyMock.anyObject());
        logSaverListener.testLogSaved(
                EasyMock.eq(LOGCAT_NAME_TEST),
                EasyMock.eq(LogDataType.LOGCAT),
                (InputStreamSource) EasyMock.anyObject(),
                (LogFile) EasyMock.anyObject());
        logSaverListener.logAssociation(EasyMock.eq(LOGCAT_NAME_TEST), EasyMock.anyObject());
        logSaverListener.testLog(
                EasyMock.eq(LOGCAT_NAME_TEARDOWN),
                EasyMock.eq(LogDataType.LOGCAT),
                (InputStreamSource) EasyMock.anyObject());
        logSaverListener.testLogSaved(
                EasyMock.eq(LOGCAT_NAME_TEARDOWN),
                EasyMock.eq(LogDataType.LOGCAT),
                (InputStreamSource) EasyMock.anyObject(),
                (LogFile) EasyMock.anyObject());
        logSaverListener.logAssociation(EasyMock.eq(LOGCAT_NAME_TEARDOWN), EasyMock.anyObject());
        logSaverListener.testLog(
                EasyMock.eq(TestInvocation.TRADEFED_LOG_NAME),
                EasyMock.eq(LogDataType.TEXT),
                (InputStreamSource) EasyMock.anyObject());
        logSaverListener.testLogSaved(
                EasyMock.eq(TestInvocation.TRADEFED_LOG_NAME),
                EasyMock.eq(LogDataType.TEXT),
                (InputStreamSource) EasyMock.anyObject(),
                (LogFile) EasyMock.anyObject());
        logSaverListener.logAssociation(
                EasyMock.eq(TestInvocation.TRADEFED_LOG_NAME), EasyMock.anyObject());
        logSaverListener.invocationEnded(EasyMock.anyLong());
        EasyMock.expect(logSaverListener.getSummary()).andReturn(mSummary);

        IRemoteTest test = EasyMock.createMock(IRemoteTest.class);
        setupMockSuccessListeners();
        test.run((ITestInvocationListener)EasyMock.anyObject());
        setupNormalInvoke(test);
        EasyMock.replay(logSaverListener, mockRescheduler);
        mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
        verifyMocks(test, logSaverListener, mockRescheduler);
        assertEquals(2, mUriCapture.getValue().size());
    }

    /**
     * Test the {@link TestInvocation#invoke(IInvocationContext, IConfiguration, IRescheduler,
     * ITestInvocationListener[])}
     * scenario with {@link IStrictShardableTest} when a shard index is given.
     */
    public void testInvoke_strictShardableTest_withShardIndex() throws Throwable {
        mTestInvocation =
                new TestInvocation() {
                    @Override
                    ILogRegistry getLogRegistry() {
                        return mMockLogRegistry;
                    }

                    @Override
                    public IInvocationExecution createInvocationExec(boolean isSandboxed) {
                        return new InvocationExecution() {
                            @Override
                            protected IShardHelper createShardHelper() {
                                return new StrictShardHelper();
                            }
                        };
                    }

                    @Override
                    protected void setExitCode(ExitCode code, Throwable stack) {
                        // empty on purpose
                    }

                    @Override
                    InvocationScope getInvocationScope() {
                        // Avoid re-entry in the current TF invocation scope for unit tests.
                        return new InvocationScope();
                    }
                };
        String[] commandLine = {"config", "arg"};
        int shardCount = 10;
        int shardIndex = 5;
        IStrictShardableTest test = EasyMock.createMock(IStrictShardableTest.class);
        IRemoteTest testShard = EasyMock.createMock(IRemoteTest.class);
        mStubConfiguration.setTest(test);
        mStubConfiguration.setCommandLine(commandLine);
        mStubConfiguration.getCommandOptions().setShardCount(shardCount);
        mStubConfiguration.getCommandOptions().setShardIndex(shardIndex);

        setupInvokeWithBuild();
        setupMockSuccessListeners();
        EasyMock.expect(mMockBuildProvider.getBuild()).andReturn(mMockBuildInfo);
        mMockBuildInfo.addBuildAttribute("command_line_args", "config arg");
        mMockBuildInfo.addBuildAttribute("shard_count", "10");
        mMockBuildInfo.addBuildAttribute("shard_index", "5");
        EasyMock.expect(test.getTestShard(shardCount, shardIndex)).andReturn(testShard);
        testShard.run((ITestInvocationListener)EasyMock.anyObject());
        mMockPreparer.setUp(mMockDevice, mMockBuildInfo);
        replayMocks(test, testShard);

        mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);

        verifyMocks(test, testShard);
    }

    /**
     * Test the {@link TestInvocation#invoke(IInvocationContext, IConfiguration, IRescheduler,
     * ITestInvocationListener[])}
     * scenario with non-{@link IStrictShardableTest} when shard index 0 is given.
     */
    public void testInvoke_nonStrictShardableTest_withShardIndexZero() throws Throwable {
        String[] commandLine = {"config", "arg"};
        int shardCount = 10;
        int shardIndex = 0;
        IRemoteTest test = EasyMock.createMock(IRemoteTest.class);
        mStubConfiguration.setTest(test);
        mStubConfiguration.setCommandLine(commandLine);
        mStubConfiguration.getCommandOptions().setShardCount(shardCount);
        mStubConfiguration.getCommandOptions().setShardIndex(shardIndex);

        setupInvokeWithBuild();
        setupMockSuccessListeners();
        EasyMock.expect(mMockBuildProvider.getBuild()).andReturn(mMockBuildInfo);
        mMockBuildInfo.addBuildAttribute("command_line_args", "config arg");
        mMockBuildInfo.addBuildAttribute("shard_count", "10");
        mMockBuildInfo.addBuildAttribute("shard_index", "0");
        test.run((ITestInvocationListener)EasyMock.anyObject());
        mMockPreparer.setUp(mMockDevice, mMockBuildInfo);
        replayMocks(test);

        mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);

        verifyMocks(test);
    }

    /**
     * Test the {@link TestInvocation#invoke(IInvocationContext, IConfiguration, IRescheduler,
     * ITestInvocationListener[])}
     * scenario with non-{@link IStrictShardableTest} when a shard index non-0 is given.
     */
    public void testInvoke_nonStrictShardableTest_withShardIndexNonZero() throws Throwable {
        mTestInvocation =
                new TestInvocation() {
                    @Override
                    ILogRegistry getLogRegistry() {
                        return mMockLogRegistry;
                    }

                    @Override
                    public IInvocationExecution createInvocationExec(boolean isSandboxed) {
                        return new InvocationExecution() {
                            @Override
                            protected IShardHelper createShardHelper() {
                                return new StrictShardHelper();
                            }
                        };
                    }

                    @Override
                    protected void setExitCode(ExitCode code, Throwable stack) {
                        // empty on purpose
                    }

                    @Override
                    InvocationScope getInvocationScope() {
                        // Avoid re-entry in the current TF invocation scope for unit tests.
                        return new InvocationScope();
                    }
                };
        String[] commandLine = {"config", "arg"};
        int shardCount = 10;
        int shardIndex = 1;
        IStrictShardableTest shardableTest = EasyMock.createMock(IStrictShardableTest.class);
        IRemoteTest test = EasyMock.createMock(IRemoteTest.class);
        EasyMock.expect(shardableTest.getTestShard(10, 1)).andReturn(test);
        test.run((ITestInvocationListener)EasyMock.anyObject());
        EasyMock.expectLastCall();
        mStubConfiguration.setTest(shardableTest);
        mStubConfiguration.setCommandLine(commandLine);
        mStubConfiguration.getCommandOptions().setShardCount(shardCount);
        mStubConfiguration.getCommandOptions().setShardIndex(shardIndex);

        setupInvokeWithBuild();
        setupMockSuccessListeners();
        EasyMock.expect(mMockBuildProvider.getBuild()).andReturn(mMockBuildInfo);
        mMockBuildInfo.addBuildAttribute("command_line_args", "config arg");
        mMockBuildInfo.addBuildAttribute("shard_count", "10");
        mMockBuildInfo.addBuildAttribute("shard_index", "1");
        mMockPreparer.setUp(mMockDevice, mMockBuildInfo);
        replayMocks(shardableTest, test);

        mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);

        verifyMocks(shardableTest, test);
    }

    /**
     * Test the test-tag is set when the IBuildInfo's test-tag is not.
     */
    public void testInvoke_testtag() throws Throwable {
        String[] commandLine = {"run", "empty"};
        mStubConfiguration.setCommandLine(commandLine);
        mStubConfiguration.getCommandOptions().setTestTag("not-default");

        setupInvoke();
        EasyMock.expect(mMockDevice.getLogcat()).andReturn(EMPTY_STREAM_SOURCE).times(3);
        mMockDevice.clearLogcat();
        EasyMock.expectLastCall().times(3);
        EasyMock.expect(mMockLogger.getLog()).andReturn(EMPTY_STREAM_SOURCE);
        mMockBuildInfo.setDeviceSerial(SERIAL);
        mMockBuildProvider.cleanUp(mMockBuildInfo);
        EasyMock.expectLastCall().times(2);
        setupMockSuccessListeners();
        EasyMock.expect(mMockBuildProvider.getBuild()).andReturn(mMockBuildInfo);
        mMockBuildInfo.addBuildAttribute("command_line_args", "run empty");
        mMockPreparer.setUp(mMockDevice, mMockBuildInfo);
        // Default build is "stub" so we set the test-tag
        mMockBuildInfo.setTestTag(EasyMock.eq("not-default"));
        EasyMock.expectLastCall();
        EasyMock.expect(mMockBuildInfo.getTestTag()).andStubReturn("stub");
        mMockLogRegistry.unregisterLogger();
        mMockLogRegistry.dumpToGlobalLog(mMockLogger);
        mMockLogger.closeLog();
        replayMocks();
        mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
        verifyMocks();
    }

    /**
     * Test the test-tag of the IBuildInfo is not modified when the CommandOption default test-tag
     * is not modified.
     */
    public void testInvoke_testtag_notset() throws Throwable {
        String[] commandLine = {"run", "empty"};
        mStubConfiguration.setCommandLine(commandLine);
        setupInvoke();
        EasyMock.expect(mMockDevice.getLogcat()).andReturn(EMPTY_STREAM_SOURCE).times(3);
        mMockDevice.clearLogcat();
        EasyMock.expectLastCall().times(3);
        EasyMock.expect(mMockLogger.getLog()).andReturn(EMPTY_STREAM_SOURCE);
        mMockBuildInfo.setDeviceSerial(SERIAL);
        mMockBuildProvider.cleanUp(mMockBuildInfo);
        EasyMock.expectLastCall().times(2);
        setupMockSuccessListeners();
        EasyMock.expect(mMockBuildProvider.getBuild()).andReturn(mMockBuildInfo);
        mMockBuildInfo.addBuildAttribute("command_line_args", "run empty");
        mMockPreparer.setUp(mMockDevice, mMockBuildInfo);
        EasyMock.expect(mMockBuildInfo.getTestTag()).andStubReturn("buildprovidertesttag");
        mMockLogRegistry.dumpToGlobalLog(mMockLogger);
        mMockLogRegistry.unregisterLogger();
        mMockLogger.closeLog();
        replayMocks();
        mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
        verifyMocks();
    }

    /**
     * Test the test-tag of the IBuildInfo is not set and Command Option is not set either.
     * A default 'stub' test-tag is set to ensure reporting is done.
     */
    public void testInvoke_notesttag() throws Throwable {
        String[] commandLine = {"run", "empty"};
        mStubConfiguration.setCommandLine(commandLine);
        setupInvoke();
        EasyMock.expect(mMockDevice.getLogcat()).andReturn(EMPTY_STREAM_SOURCE).times(3);
        mMockDevice.clearLogcat();
        EasyMock.expectLastCall().times(3);
        EasyMock.expect(mMockLogger.getLog()).andReturn(EMPTY_STREAM_SOURCE);
        mMockBuildInfo.setDeviceSerial(SERIAL);
        mMockBuildProvider.cleanUp(mMockBuildInfo);
        EasyMock.expectLastCall().times(2);
        setupMockSuccessListeners();
        EasyMock.expect(mMockBuildProvider.getBuild()).andReturn(mMockBuildInfo);
        mMockBuildInfo.addBuildAttribute("command_line_args", "run empty");
        mMockPreparer.setUp(mMockDevice, mMockBuildInfo);
        EasyMock.expect(mMockBuildInfo.getTestTag()).andStubReturn(null);
        mMockBuildInfo.setTestTag(EasyMock.eq("stub"));
        EasyMock.expectLastCall();
        mMockLogRegistry.dumpToGlobalLog(mMockLogger);
        mMockLogRegistry.unregisterLogger();
        mMockLogger.closeLog();
        replayMocks();
        mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
        verifyMocks();
    }

    /**
     * Helper tests class to expose all the interfaces needed for the tests.
     */
    private interface IFakeBuildProvider extends IDeviceBuildProvider, IInvocationContextReceiver {
    }

    /**
     * Test the injection of test-tag from TestInvocation to the build provider via the
     * {@link IInvocationContextReceiver}.
     */
    public void testInvoke_buildProviderNeedTestTag() throws Throwable {
        final String testTag = "THISISTHETAG";
        String[] commandLine = {"run", "empty"};
        mStubConfiguration.setCommandLine(commandLine);
        ICommandOptions commandOption = new CommandOptions();
        commandOption.setTestTag(testTag);
        IFakeBuildProvider mockProvider = EasyMock.createMock(IFakeBuildProvider.class);
        mStubConfiguration.setBuildProvider(mockProvider);
        mStubConfiguration.setCommandOptions(commandOption);
        setupInvoke();
        EasyMock.expect(mMockDevice.getLogcat()).andReturn(EMPTY_STREAM_SOURCE).times(3);
        mMockDevice.clearLogcat();
        EasyMock.expectLastCall().times(3);
        EasyMock.expect(mMockLogger.getLog()).andReturn(EMPTY_STREAM_SOURCE);
        mMockBuildInfo.setDeviceSerial(SERIAL);
        setupMockSuccessListeners();
        mMockBuildInfo.addBuildAttribute("command_line_args", "run empty");
        mMockPreparer.setUp(mMockDevice, mMockBuildInfo);
        EasyMock.expect(mMockBuildInfo.getTestTag()).andStubReturn(null);
        // Validate proper tag is set on the build.
        mMockBuildInfo.setTestTag(EasyMock.eq(testTag));
        mockProvider.setInvocationContext((IInvocationContext)EasyMock.anyObject());
        EasyMock.expect(mockProvider.getBuild(mMockDevice)).andReturn(mMockBuildInfo);
        mockProvider.cleanUp(mMockBuildInfo);
        EasyMock.expectLastCall().times(2);
        mMockLogRegistry.dumpToGlobalLog(mMockLogger);
        mMockLogRegistry.unregisterLogger();
        mMockLogger.closeLog();

        replayMocks(mockProvider);
        mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
        verifyMocks(mockProvider);
    }

    /**
     * Set up expected conditions for normal run up to the part where tests are run.
     *
     * @param test the {@link Test} to use.
     */
    private void setupNormalInvoke(IRemoteTest test) throws Throwable {
        setupInvokeWithBuild();
        mStubConfiguration.setTest(test);
        mStubMultiConfiguration.setTest(test);
        EasyMock.expect(mMockBuildProvider.getBuild()).andReturn(mMockBuildInfo);

        mMockPreparer.setUp(mMockDevice, mMockBuildInfo);
        replayMocks(test);
    }

    /**
     * Set up expected calls that occur on every invoke, regardless of result
     */
    private void setupInvoke() {
        mMockDevice.clearLastConnectedWifiNetwork();
        mMockDevice.setOptions((TestDeviceOptions)EasyMock.anyObject());
        mMockDevice.startLogcat();
        mMockDevice.clearLastConnectedWifiNetwork();
        mMockDevice.stopLogcat();
    }

    /**
     * Set up expected calls that occur on every invoke that gets a valid build
     */
    private void setupInvokeWithBuild() {
        setupInvoke();
        EasyMock.expect(mMockDevice.getLogcat()).andReturn(EMPTY_STREAM_SOURCE).times(3);
        mMockDevice.clearLogcat();
        EasyMock.expectLastCall().times(3);

        EasyMock.expect(mMockLogger.getLog()).andReturn(EMPTY_STREAM_SOURCE);
        mMockBuildInfo.setDeviceSerial(SERIAL);
        mMockBuildProvider.cleanUp(mMockBuildInfo);
        EasyMock.expectLastCall().anyTimes();
        mMockBuildInfo.setTestTag(EasyMock.eq("stub"));
        EasyMock.expectLastCall();
        EasyMock.expect(mMockBuildInfo.getTestTag()).andStubReturn("");

        mMockLogRegistry.unregisterLogger();
        mMockLogRegistry.dumpToGlobalLog(mMockLogger);
        mMockLogger.closeLog();
    }

    /**
     * Set up expected conditions for the test InvocationListener and SummaryListener
     *
     * <p>The order of calls for a single listener should be:
     *
     * <ol>
     *   <li>invocationStarted
     *   <li>testLog(LOGCAT_NAME_SETUP, ...) (if no build or retrieval error)
     *   <li>invocationFailed (if run failed)
     *   <li>testLog(LOGCAT_NAME_ERROR, ...) (if build retrieval error)
     *   <li>testLog(LOGCAT_NAME_TEST, ...) (otherwise)
     *   <li>testLog(build error bugreport, ...) (otherwise and if build error)
     *   <li>testLog(LOGCAT_NAME_TEARDOWN, ...) (otherwise)
     *   <li>testLog(TRADEFED_LOG_NAME, ...)
     *   <li>putSummary (for an ITestSummaryListener)
     *   <li>invocationEnded
     *   <li>getSummary (for an ITestInvocationListener)
     * </ol>
     *
     * However note that, across all listeners, any getSummary call will precede all putSummary
     * calls.
     */
    private void setupMockListeners(InvocationStatus status, Throwable throwable)
            throws IOException {
        // invocationStarted
        mMockLogSaver.invocationStarted(mStubInvocationMetadata);
        mMockTestListener.invocationStarted(mStubInvocationMetadata);
        mMockSummaryListener.invocationStarted(mStubInvocationMetadata);

        if (!(throwable instanceof BuildRetrievalError)) {
            EasyMock.expect(
                            mMockLogSaver.saveLogData(
                                    EasyMock.eq(LOGCAT_NAME_SETUP),
                                    EasyMock.eq(LogDataType.LOGCAT),
                                    (InputStream) EasyMock.anyObject()))
                    .andReturn(new LogFile(PATH, URL, LogDataType.TEXT));
            mMockTestListener.testLog(
                    EasyMock.eq(LOGCAT_NAME_SETUP),
                    EasyMock.eq(LogDataType.LOGCAT),
                    (InputStreamSource) EasyMock.anyObject());
            mMockSummaryListener.testLog(
                    EasyMock.eq(LOGCAT_NAME_SETUP),
                    EasyMock.eq(LogDataType.LOGCAT),
                    (InputStreamSource) EasyMock.anyObject());
        }

        // invocationFailed
        if (!status.equals(InvocationStatus.SUCCESS)) {
            mMockTestListener.invocationFailed(EasyMock.eq(throwable));
            mMockSummaryListener.invocationFailed(EasyMock.eq(throwable));
        }

        if (throwable instanceof BuildRetrievalError) {
            // Handle logcat error listeners
            EasyMock.expect(
                            mMockLogSaver.saveLogData(
                                    EasyMock.eq(LOGCAT_NAME_ERROR),
                                    EasyMock.eq(LogDataType.LOGCAT),
                                    (InputStream) EasyMock.anyObject()))
                    .andReturn(new LogFile(PATH, URL, LogDataType.TEXT));
            mMockTestListener.testLog(
                    EasyMock.eq(LOGCAT_NAME_ERROR),
                    EasyMock.eq(LogDataType.LOGCAT),
                    (InputStreamSource) EasyMock.anyObject());
            mMockSummaryListener.testLog(
                    EasyMock.eq(LOGCAT_NAME_ERROR),
                    EasyMock.eq(LogDataType.LOGCAT),
                    (InputStreamSource) EasyMock.anyObject());
        } else {
            // Handle test logcat listeners
            EasyMock.expect(
                            mMockLogSaver.saveLogData(
                                    EasyMock.eq(LOGCAT_NAME_TEST),
                                    EasyMock.eq(LogDataType.LOGCAT),
                                    (InputStream) EasyMock.anyObject()))
                    .andReturn(new LogFile(PATH, URL, LogDataType.TEXT));
            mMockTestListener.testLog(
                    EasyMock.eq(LOGCAT_NAME_TEST),
                    EasyMock.eq(LogDataType.LOGCAT),
                    (InputStreamSource) EasyMock.anyObject());
            mMockSummaryListener.testLog(
                    EasyMock.eq(LOGCAT_NAME_TEST),
                    EasyMock.eq(LogDataType.LOGCAT),
                    (InputStreamSource) EasyMock.anyObject());
            // Handle build error bugreport listeners
            if (throwable instanceof BuildError) {
                EasyMock.expect(
                                mMockDevice.logBugreport(
                                        EasyMock.eq(
                                                TestInvocation.BUILD_ERROR_BUGREPORT_NAME
                                                        + "_"
                                                        + SERIAL),
                                        EasyMock.anyObject()))
                        .andReturn(true);
            }
            // Handle teardown logcat listeners
            EasyMock.expect(
                            mMockLogSaver.saveLogData(
                                    EasyMock.eq(LOGCAT_NAME_TEARDOWN),
                                    EasyMock.eq(LogDataType.LOGCAT),
                                    (InputStream) EasyMock.anyObject()))
                    .andReturn(new LogFile(PATH, URL, LogDataType.TEXT));
            mMockTestListener.testLog(
                    EasyMock.eq(LOGCAT_NAME_TEARDOWN),
                    EasyMock.eq(LogDataType.LOGCAT),
                    (InputStreamSource) EasyMock.anyObject());
            mMockSummaryListener.testLog(
                    EasyMock.eq(LOGCAT_NAME_TEARDOWN),
                    EasyMock.eq(LogDataType.LOGCAT),
                    (InputStreamSource) EasyMock.anyObject());
        }

        EasyMock.expect(
                        mMockLogSaver.saveLogData(
                                EasyMock.eq(TestInvocation.TRADEFED_LOG_NAME),
                                EasyMock.eq(LogDataType.TEXT),
                                (InputStream) EasyMock.anyObject()))
                .andReturn(new LogFile(PATH, URL, LogDataType.TEXT));
        mMockTestListener.testLog(EasyMock.eq(TestInvocation.TRADEFED_LOG_NAME),
                EasyMock.eq(LogDataType.TEXT), (InputStreamSource)EasyMock.anyObject());
        mMockSummaryListener.testLog(EasyMock.eq(TestInvocation.TRADEFED_LOG_NAME),
                EasyMock.eq(LogDataType.TEXT), (InputStreamSource)EasyMock.anyObject());

        // invocationEnded, getSummary (mMockTestListener)
        mMockTestListener.invocationEnded(EasyMock.anyLong());
        EasyMock.expect(mMockTestListener.getSummary()).andReturn(mSummary);

        // putSummary, invocationEnded (mMockSummaryListener)
        mMockSummaryListener.putSummary(EasyMock.capture(mUriCapture));
        mMockSummaryListener.invocationEnded(EasyMock.anyLong());
        mMockLogSaver.invocationEnded(EasyMock.anyLong());
    }

    /**
     * Test the {@link TestInvocation#invoke(IInvocationContext, IConfiguration, IRescheduler,
     * ITestInvocationListener[])} scenario with {@link IShardableTest}.
     */
    public void testInvoke_shardableTest_legacy() throws Throwable {
        String command = "empty --test-tag t";
        String[] commandLine = {"empty", "--test-tag", "t"};
        int shardCount = 2;
        IShardableTest test = EasyMock.createMock(IShardableTest.class);
        List<IRemoteTest> shards = new ArrayList<>();
        IRemoteTest shard1 = EasyMock.createMock(IRemoteTest.class);
        IRemoteTest shard2 = EasyMock.createMock(IRemoteTest.class);
        shards.add(shard1);
        shards.add(shard2);
        EasyMock.expect(test.split()).andReturn(shards);
        mStubConfiguration.setTest(test);
        mStubConfiguration.setCommandLine(commandLine);
        mMockBuildProvider.cleanUp(mMockBuildInfo);
        setupInvoke();
        setupNShardInvocation(shardCount, command);
        mMockLogRegistry.dumpToGlobalLog(mMockLogger);
        replayMocks(test, mockRescheduler, shard1, shard2);
        mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
        verifyMocks(test, mockRescheduler, shard1, shard2);
    }

    /**
     * Test that {@link TestInvocation#logDeviceBatteryLevel(IInvocationContext, String)} is not
     * adding battery information for placeholder device.
     */
    public void testLogDeviceBatteryLevel_placeholderDevice() {
        final String fakeEvent = "event";
        IInvocationContext context = new InvocationContext();
        ITestDevice device1 = EasyMock.createMock(ITestDevice.class);
        EasyMock.expect(device1.getIDevice()).andReturn(new StubDevice("serial1"));
        context.addAllocatedDevice("device1", device1);
        EasyMock.replay(device1);
        mTestInvocation.logDeviceBatteryLevel(context, fakeEvent);
        EasyMock.verify(device1);
        assertEquals(0, context.getAttributes().size());
    }

    /**
     * Test that {@link TestInvocation#logDeviceBatteryLevel(IInvocationContext, String)} is adding
     * battery information for physical real device.
     */
    public void testLogDeviceBatteryLevel_physicalDevice() {
        final String fakeEvent = "event";
        IInvocationContext context = new InvocationContext();
        ITestDevice device1 = EasyMock.createMock(ITestDevice.class);
        IDevice idevice = Mockito.mock(IDevice.class);
        EasyMock.expect(device1.getIDevice()).andReturn(idevice);
        SettableFuture<Integer> future = SettableFuture.create();
        future.set(50);
        doReturn(future).when(idevice).getBattery(Mockito.anyLong(), Mockito.any());
        EasyMock.expect(device1.getSerialNumber()).andReturn("serial1");
        context.addAllocatedDevice("device1", device1);
        context.addDeviceBuildInfo("device1", new BuildInfo());
        EasyMock.replay(device1);
        mTestInvocation.logDeviceBatteryLevel(context, fakeEvent);
        EasyMock.verify(device1);
        assertEquals(1, context.getBuildInfo("device1").getBuildAttributes().size());
        assertEquals(
                "50",
                context.getBuildInfo("device1")
                        .getBuildAttributes()
                        .get("serial1-battery-" + fakeEvent));
    }

    /**
     * Test that {@link TestInvocation#logDeviceBatteryLevel(IInvocationContext, String)} is adding
     * battery information for multiple physical real device.
     */
    public void testLogDeviceBatteryLevel_physicalDevice_multi() {
        final String fakeEvent = "event";
        IInvocationContext context = new InvocationContext();
        ITestDevice device1 = EasyMock.createMock(ITestDevice.class);
        IDevice idevice = Mockito.mock(IDevice.class);
        EasyMock.expect(device1.getSerialNumber()).andReturn("serial1");
        EasyMock.expect(device1.getIDevice()).andReturn(idevice);
        SettableFuture<Integer> future = SettableFuture.create();
        future.set(50);
        doReturn(future).when(idevice).getBattery(Mockito.anyLong(), Mockito.any());
        ITestDevice device2 = EasyMock.createMock(ITestDevice.class);
        EasyMock.expect(device2.getIDevice()).andReturn(idevice);
        EasyMock.expect(device2.getSerialNumber()).andReturn("serial2");
        context.addAllocatedDevice("device1", device1);
        context.addDeviceBuildInfo("device1", new BuildInfo());
        context.addAllocatedDevice("device2", device2);
        context.addDeviceBuildInfo("device2", new BuildInfo());
        EasyMock.replay(device1, device2);
        mTestInvocation.logDeviceBatteryLevel(context, fakeEvent);
        EasyMock.verify(device1, device2);
        assertEquals(1, context.getBuildInfo("device1").getBuildAttributes().size());
        assertEquals(1, context.getBuildInfo("device2").getBuildAttributes().size());
        assertEquals(
                "50",
                context.getBuildInfo("device1")
                        .getBuildAttributes()
                        .get("serial1-battery-" + fakeEvent));
        assertEquals(
                "50",
                context.getBuildInfo("device2")
                        .getBuildAttributes()
                        .get("serial2-battery-" + fakeEvent));
    }

    /**
     * Test that {@link TestInvocation#logDeviceBatteryLevel(IInvocationContext, String)} is adding
     * battery information for multiple physical real device, and ignore stub device if any.
     */
    public void testLogDeviceBatteryLevel_physicalDevice_stub_multi() {
        final String fakeEvent = "event";
        IInvocationContext context = new InvocationContext();
        ITestDevice device1 = EasyMock.createMock(ITestDevice.class);
        IDevice idevice = Mockito.mock(IDevice.class);
        EasyMock.expect(device1.getSerialNumber()).andReturn("serial1");
        EasyMock.expect(device1.getIDevice()).andReturn(idevice);
        SettableFuture<Integer> future = SettableFuture.create();
        future.set(50);
        doReturn(future).when(idevice).getBattery(Mockito.anyLong(), Mockito.any());
        ITestDevice device2 = EasyMock.createMock(ITestDevice.class);
        EasyMock.expect(device2.getIDevice()).andReturn(idevice);
        EasyMock.expect(device2.getSerialNumber()).andReturn("serial2");
        ITestDevice device3 = EasyMock.createMock(ITestDevice.class);
        EasyMock.expect(device1.getIDevice()).andStubReturn(new StubDevice("stub1"));
        ITestDevice device4 = EasyMock.createMock(ITestDevice.class);
        EasyMock.expect(device1.getIDevice()).andStubReturn(new StubDevice("stub2"));
        context.addAllocatedDevice("device1", device1);
        context.addDeviceBuildInfo("device1", new BuildInfo());
        context.addAllocatedDevice("device2", device2);
        context.addDeviceBuildInfo("device2", new BuildInfo());
        context.addAllocatedDevice("device3", device3);
        context.addAllocatedDevice("device4", device4);
        EasyMock.replay(device1, device2);
        mTestInvocation.logDeviceBatteryLevel(context, fakeEvent);
        EasyMock.verify(device1, device2);
        assertEquals(1, context.getBuildInfo("device1").getBuildAttributes().size());
        assertEquals(1, context.getBuildInfo("device2").getBuildAttributes().size());
        assertEquals(
                "50",
                context.getBuildInfo("device1")
                        .getBuildAttributes()
                        .get("serial1-battery-" + fakeEvent));
        assertEquals(
                "50",
                context.getBuildInfo("device2")
                        .getBuildAttributes()
                        .get("serial2-battery-" + fakeEvent));
    }

    /** Helper to set the expectation for N number of shards. */
    private void setupNShardInvocation(int numShard, String commandLine) throws Exception {
        mMockBuildInfo.setTestTag(EasyMock.eq("stub"));
        EasyMock.expectLastCall();
        EasyMock.expect(mMockBuildProvider.getBuild()).andReturn(mMockBuildInfo);
        EasyMock.expect(mMockBuildInfo.getTestTag()).andStubReturn("");
        mMockBuildInfo.addBuildAttribute("command_line_args", commandLine);
        mMockTestListener.invocationStarted((IInvocationContext)EasyMock.anyObject());
        EasyMock.expectLastCall();
        mMockSummaryListener.invocationStarted((IInvocationContext)EasyMock.anyObject());
        EasyMock.expectLastCall();
        EasyMock.expect(mMockLogger.clone()).andReturn(mMockLogger).times(numShard);
        EasyMock.expect(mMockBuildInfo.clone()).andReturn(mMockBuildInfo).times(numShard);
        EasyMock.expect(mockRescheduler.scheduleConfig(EasyMock.anyObject()))
                .andReturn(true).times(numShard);
        mMockBuildInfo.setDeviceSerial(SERIAL);
        EasyMock.expectLastCall();
        mMockBuildProvider.cleanUp(EasyMock.anyObject());
        EasyMock.expectLastCall();
    }

    private void setupMockSuccessListeners() throws IOException {
        setupMockListeners(InvocationStatus.SUCCESS, null);
    }

    private void setupMockFailureListeners(Throwable throwable) throws IOException {
        setupMockListeners(InvocationStatus.FAILED, throwable);
    }

    private void verifySummaryListener() {
        // Check that we captured the expected uris List
        List<TestSummary> summaries = mUriCapture.getValue();
        assertEquals(1, summaries.size());
        assertEquals(mSummary, summaries.get(0));
    }

    /**
     * Verify all mock objects received expected calls
     */
    private void verifyMocks(Object... mocks) {
        // note: intentionally exclude configuration from verification - don't care
        // what methods are called
        EasyMock.verify(mMockTestListener, mMockSummaryListener, mMockPreparer,
                mMockBuildProvider, mMockLogger, mMockBuildInfo, mMockLogRegistry,
                mMockLogSaver);
        if (mocks.length > 0) {
            EasyMock.verify(mocks);
        }
    }

    /**
     * Switch all mock objects into replay mode.
     */
    private void replayMocks(Object... mocks) {
        EasyMock.replay(mMockTestListener, mMockSummaryListener, mMockPreparer,
                mMockBuildProvider, mMockLogger, mMockBuildInfo, mMockLogRegistry,
                mMockLogSaver, mMockDevice, mMockConfigFactory);
        if (mocks.length > 0) {
            EasyMock.replay(mocks);
        }
    }

    /**
     * Interface for testing device config pass through.
     */
    private interface DeviceConfigTest extends IRemoteTest, IDeviceTest {

    }

    /**
     * Test {@link INativeDevice#preInvocationSetup(IBuildInfo info)} is called when command option
     * skip-pre-device-setup is not set.
     */
    public void testNotSkipPreDeviceSetup() throws Throwable {
        IInvocationContext context = new InvocationContext();
        ITestDevice device1 = EasyMock.createMock(ITestDevice.class);
        IDevice idevice = Mockito.mock(IDevice.class);
        context.addAllocatedDevice("DEFAULT_DEVICE", device1);
        EasyMock.expect(device1.getSerialNumber()).andReturn("serial1").anyTimes();
        EasyMock.expect(device1.getIDevice()).andReturn(idevice).anyTimes();
        EasyMock.expect(device1.getLogcat()).andReturn(EMPTY_STREAM_SOURCE).times(1);
        device1.clearLogcat();
        EasyMock.expectLastCall().once();
        device1.preInvocationSetup((IBuildInfo) EasyMock.anyObject());
        EasyMock.expectLastCall().once();

        CommandOptions commandOption = new CommandOptions();
        OptionSetter setter = new OptionSetter(commandOption);
        setter.setOptionValue("skip-pre-device-setup", "false");
        mStubConfiguration.setCommandOptions(commandOption);

        EasyMock.expect(mMockPreparer.isDisabled()).andReturn(true);
        // Not expect isTearDownDisabled.

        ITestInvocationListener listener = EasyMock.createStrictMock(ITestInvocationListener.class);
        listener.testLog(
                EasyMock.eq(LOGCAT_NAME_SETUP),
                EasyMock.eq(LogDataType.LOGCAT),
                (InputStreamSource) EasyMock.anyObject());

        EasyMock.replay(device1, listener, mMockPreparer);
        new InvocationExecution().doSetup(context, mStubConfiguration, listener);
        EasyMock.verify(device1, listener, mMockPreparer);

    }

    /**
     * Test {@link INativeDevice#preInvocationSetup(IBuildInfo info)} is not called when command
     * option skip-pre-device-setup is set.
     */
    public void testSkipPreDeviceSetup() throws Throwable {
        IInvocationContext context = new InvocationContext();
        ITestDevice device1 = EasyMock.createMock(ITestDevice.class);
        IDevice idevice = Mockito.mock(IDevice.class);
        context.addAllocatedDevice("DEFAULT_DEVICE", device1);
        EasyMock.expect(device1.getSerialNumber()).andReturn("serial1").anyTimes();
        EasyMock.expect(device1.getIDevice()).andReturn(idevice).anyTimes();
        EasyMock.expect(device1.getLogcat()).andReturn(EMPTY_STREAM_SOURCE).times(1);
        device1.clearLogcat();
        EasyMock.expectLastCall().once();

        CommandOptions commandOption = new CommandOptions();
        OptionSetter setter = new OptionSetter(commandOption);
        setter.setOptionValue("skip-pre-device-setup", "true");
        mStubConfiguration.setCommandOptions(commandOption);

        EasyMock.expect(mMockPreparer.isDisabled()).andReturn(true);
        // Not expect isTearDownDisabled

        ITestInvocationListener listener = EasyMock.createStrictMock(ITestInvocationListener.class);
        listener.testLog(
                EasyMock.eq(LOGCAT_NAME_SETUP),
                EasyMock.eq(LogDataType.LOGCAT),
                (InputStreamSource) EasyMock.anyObject());

        EasyMock.replay(device1, listener, mMockPreparer);
        new InvocationExecution().doSetup(context, mStubConfiguration, listener);
        EasyMock.verify(device1, listener, mMockPreparer);
    }

    /**
     * Test when a {@link IDeviceBuildInfo} is passing through we do not attempt to add any external
     * directories when there is none coming from environment.
     */
    public void testInvoke_deviceInfoBuild_noEnv() throws Throwable {
        mTestInvocation =
                new TestInvocation() {
                    @Override
                    ILogRegistry getLogRegistry() {
                        return mMockLogRegistry;
                    }

                    @Override
                    public IInvocationExecution createInvocationExec(boolean isSandboxed) {
                        return new InvocationExecution() {
                            @Override
                            protected IShardHelper createShardHelper() {
                                return new ShardHelper();
                            }

                            @Override
                            File getExternalTestCasesDirs(EnvVariable envVar) {
                                // Return empty list to ensure we do not have any environment loaded
                                return null;
                            }
                        };
                    }

                    @Override
                    protected void setExitCode(ExitCode code, Throwable stack) {
                        // empty on purpose
                    }

                    @Override
                    InvocationScope getInvocationScope() {
                        // Avoid re-entry in the current TF invocation scope for unit tests.
                        return new InvocationScope();
                    }
                };
        mMockBuildInfo = EasyMock.createMock(IDeviceBuildInfo.class);
        EasyMock.expect(mMockBuildInfo.getProperties()).andStubReturn(new HashSet<>());
        IRemoteTest test = EasyMock.createNiceMock(IRemoteTest.class);
        ITargetCleaner mockCleaner = EasyMock.createMock(ITargetCleaner.class);
        EasyMock.expect(mockCleaner.isDisabled()).andReturn(false).times(2);
        EasyMock.expect(mockCleaner.isTearDownDisabled()).andReturn(false);
        mockCleaner.setUp(mMockDevice, mMockBuildInfo);
        mockCleaner.tearDown(mMockDevice, mMockBuildInfo, null);
        mStubConfiguration.getTargetPreparers().add(mockCleaner);

        File tmpTestsDir = FileUtil.createTempDir("invocation-tests-dir");
        try {
            EasyMock.expect(((IDeviceBuildInfo) mMockBuildInfo).getTestsDir())
                    .andReturn(tmpTestsDir);
            setupMockSuccessListeners();
            setupNormalInvoke(test);
            EasyMock.replay(mockCleaner, mockRescheduler);
            mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
            verifyMocks(mockCleaner, mockRescheduler);
            verifySummaryListener();
        } finally {
            FileUtil.recursiveDelete(tmpTestsDir);
        }
    }

    /**
     * Test when a {@link IDeviceBuildInfo} is passing through we attempt to add the external
     * directories to it when they are available.
     */
    public void testInvoke_deviceInfoBuild_withEnv() throws Throwable {
        File tmpTestsDir = FileUtil.createTempDir("invocation-tests-dir");
        File tmpExternalTestsDir = FileUtil.createTempDir("external-tf-dir");
        File tmpTestsFile = FileUtil.createTempFile("testsfile", "txt", tmpExternalTestsDir);
        try {
            mTestInvocation =
                    new TestInvocation() {
                        @Override
                        ILogRegistry getLogRegistry() {
                            return mMockLogRegistry;
                        }

                        @Override
                        public IInvocationExecution createInvocationExec(boolean isSandboxed) {
                            return new InvocationExecution() {
                                @Override
                                protected IShardHelper createShardHelper() {
                                    return new ShardHelper();
                                }

                                @Override
                                File getExternalTestCasesDirs(EnvVariable envVar) {
                                    if (EnvVariable.ANDROID_TARGET_OUT_TESTCASES.equals(envVar)) {
                                        return tmpExternalTestsDir;
                                    }
                                    return null;
                                }
                            };
                        }

                        @Override
                        protected void setExitCode(ExitCode code, Throwable stack) {
                            // empty on purpose
                        }

                        @Override
                        InvocationScope getInvocationScope() {
                            // Avoid re-entry in the current TF invocation scope for unit tests.
                            return new InvocationScope();
                        }
                    };
            mMockBuildInfo = EasyMock.createMock(IDeviceBuildInfo.class);
            IRemoteTest test = EasyMock.createNiceMock(IRemoteTest.class);
            ITargetCleaner mockCleaner = EasyMock.createMock(ITargetCleaner.class);
            EasyMock.expect(mockCleaner.isDisabled()).andReturn(false).times(2);
            EasyMock.expect(mockCleaner.isTearDownDisabled()).andReturn(false);
            mockCleaner.setUp(mMockDevice, mMockBuildInfo);
            mockCleaner.tearDown(mMockDevice, mMockBuildInfo, null);
            mStubConfiguration.getTargetPreparers().add(mockCleaner);

            mMockBuildInfo.setFile(
                    EasyMock.contains(ExternalLinkedDir.TARGET_LINKED_DIR.toString()),
                    EasyMock.anyObject(),
                    EasyMock.eq("v1"));
            EasyMock.expect(((IDeviceBuildInfo) mMockBuildInfo).getTestsDir())
                    .andReturn(tmpTestsDir);
            EasyMock.expect(mMockBuildInfo.getProperties()).andStubReturn(new HashSet<>());

            setupMockSuccessListeners();
            setupNormalInvoke(test);
            EasyMock.replay(mockCleaner, mockRescheduler);
            mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
            verifyMocks(mockCleaner, mockRescheduler);
            verifySummaryListener();
            // Check that the external directory was copied in the testsDir.
            assertTrue(tmpTestsDir.listFiles().length == 1);
            // external-tf-dir - the symlink is the original file name + randomized sequence
            assertTrue(
                    tmpTestsDir
                            .listFiles()[0]
                            .getName()
                            .startsWith(ExternalLinkedDir.TARGET_LINKED_DIR.toString()));
            // testsfile.txt
            assertTrue(tmpTestsDir.listFiles()[0].listFiles().length == 1);
            assertEquals(
                    tmpTestsFile.getName(), tmpTestsDir.listFiles()[0].listFiles()[0].getName());
        } finally {
            FileUtil.recursiveDelete(tmpTestsDir);
            FileUtil.recursiveDelete(tmpExternalTestsDir);
        }
    }

    /**
     * Test when a {@link IDeviceBuildInfo} is passing through we do not attempt to add the external
     * directories to it, since {@link BuildInfoProperties} is set to skip the linking.
     */
    public void testInvoke_deviceInfoBuild_withEnv_andSkipProperty() throws Throwable {
        File tmpTestsDir = FileUtil.createTempDir("invocation-tests-dir");
        File tmpExternalTestsDir = FileUtil.createTempDir("external-tf-dir");
        FileUtil.createTempFile("testsfile", "txt", tmpExternalTestsDir);
        try {
            mTestInvocation =
                    new TestInvocation() {
                        @Override
                        ILogRegistry getLogRegistry() {
                            return mMockLogRegistry;
                        }

                        @Override
                        public IInvocationExecution createInvocationExec(boolean isSandboxed) {
                            return new InvocationExecution() {
                                @Override
                                protected IShardHelper createShardHelper() {
                                    return new ShardHelper();
                                }

                                @Override
                                File getExternalTestCasesDirs(EnvVariable envVar) {
                                    return tmpExternalTestsDir;
                                }
                            };
                        }

                        @Override
                        protected void setExitCode(ExitCode code, Throwable stack) {
                            // empty on purpose
                        }

                        @Override
                        InvocationScope getInvocationScope() {
                            // Avoid re-entry in the current TF invocation scope for unit tests.
                            return new InvocationScope();
                        }
                    };
            mMockBuildInfo = EasyMock.createMock(IDeviceBuildInfo.class);
            IRemoteTest test = EasyMock.createNiceMock(IRemoteTest.class);
            ITargetCleaner mockCleaner = EasyMock.createMock(ITargetCleaner.class);
            EasyMock.expect(mockCleaner.isDisabled()).andReturn(false).times(2);
            EasyMock.expect(mockCleaner.isTearDownDisabled()).andReturn(false);
            mockCleaner.setUp(mMockDevice, mMockBuildInfo);
            mockCleaner.tearDown(mMockDevice, mMockBuildInfo, null);
            mStubConfiguration.getTargetPreparers().add(mockCleaner);

            Set<BuildInfoProperties> prop = new HashSet<>();
            prop.add(BuildInfoProperties.DO_NOT_LINK_TESTS_DIR);
            EasyMock.expect(mMockBuildInfo.getProperties()).andStubReturn(prop);

            setupMockSuccessListeners();
            setupNormalInvoke(test);
            EasyMock.replay(mockCleaner, mockRescheduler);
            mTestInvocation.invoke(mStubInvocationMetadata, mStubConfiguration, mockRescheduler);
            verifyMocks(mockCleaner, mockRescheduler);
            verifySummaryListener();
            // Check that the external directory was NOT copied in the testsDir.
            assertTrue(tmpTestsDir.listFiles().length == 0);
        } finally {
            FileUtil.recursiveDelete(tmpTestsDir);
            FileUtil.recursiveDelete(tmpExternalTestsDir);
        }
    }

    public static class TestableCollector extends BaseDeviceMetricCollector {

        @Option(name = "name")
        private String mName;

        public TestableCollector() {}

        public TestableCollector(String name) {
            mName = name;
        }

        @Override
        public void onTestRunEnd(
                DeviceMetricData runData, final Map<String, Metric> currentRunMetrics) {
            runData.addMetric(
                    mName,
                    Metric.newBuilder()
                            .setMeasurements(
                                    Measurements.newBuilder().setSingleString(mName).build()));
        }
    }

    /**
     * Test that when {@link IMetricCollector} are used, they wrap and call in sequence the listener
     * so all metrics end up on the final receiver.
     */
    public void testMetricCollectionChain() throws Exception {
        IConfiguration configuration = new Configuration("test", "description");
        StubTest test = new StubTest();
        OptionSetter setter = new OptionSetter(test);
        setter.setOptionValue("run-a-test", "true");
        configuration.setTest(test);

        List<IMetricCollector> collectors = new ArrayList<>();
        collectors.add(new TestableCollector("collector1"));
        collectors.add(new TestableCollector("collector2"));
        collectors.add(new TestableCollector("collector3"));
        collectors.add(new TestableCollector("collector4"));
        configuration.setDeviceMetricCollectors(collectors);

        mMockTestListener.testRunStarted("TestStub", 1);
        TestDescription testId = new TestDescription("StubTest", "StubMethod");
        mMockTestListener.testStarted(EasyMock.eq(testId), EasyMock.anyLong());
        mMockTestListener.testEnded(
                EasyMock.eq(testId),
                EasyMock.anyLong(),
                EasyMock.eq(new HashMap<String, Metric>()));
        Capture<HashMap<String, Metric>> captured = new Capture<>();
        mMockTestListener.testRunEnded(EasyMock.anyLong(), EasyMock.capture(captured));
        EasyMock.replay(mMockTestListener);
        new InvocationExecution()
                .runTests(mStubInvocationMetadata, configuration, mMockTestListener);
        EasyMock.verify(mMockTestListener);
        // The collectors are called in sequence
        List<String> listKeys = new ArrayList<>(captured.getValue().keySet());
        assertEquals(4, listKeys.size());
        assertEquals("collector4", listKeys.get(0));
        assertEquals("collector3", listKeys.get(1));
        assertEquals("collector2", listKeys.get(2));
        assertEquals("collector1", listKeys.get(3));
    }
}
