/*
 * Copyright (C) 2017 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.compatibility.common.tradefed.presubmit;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import com.android.compatibility.SuiteInfo;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.compatibility.common.tradefed.result.ResultReporter;
import com.android.compatibility.common.tradefed.testtype.CompatibilityTest;
import com.android.compatibility.common.util.IInvocationResult;
import com.android.compatibility.common.util.TestStatus;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.ConfigurationFactory;
import com.android.tradefed.config.OptionSetter;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.invoker.IInvocationContext;
import com.android.tradefed.invoker.InvocationContext;
import com.android.tradefed.invoker.ShardListener;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.ResultForwarder;
import com.android.tradefed.testtype.IBuildReceiver;
import com.android.tradefed.testtype.IDeviceTest;
import com.android.tradefed.testtype.IRemoteTest;
import com.android.tradefed.util.AbiUtils;
import com.android.tradefed.util.FileUtil;

import org.easymock.EasyMock;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Integration tests between {@link CompatibilityTest} and {@link ResultReporter} to ensure proper
 * flow of run and results.
 */
@RunWith(JUnit4.class)
public class IntegrationTest {

    private static final String CONFIG =
            "<configuration description=\"Auto Generated File\">\n" +
            "<test class=\"com.android.compatibility.common.tradefed.testtype.%s\">\n" +
            "    <option name=\"report-test\" value=\"%s\" />\n" +
            "    <option name=\"run-complete\" value=\"%s\" />\n" +
            "    <option name=\"test-fail\" value=\"%s\" />\n" +
            "    <option name=\"internal-retry\" value=\"%s\" />\n" +
            "</test>\n" +
            "</configuration>";
    private static final String FILENAME = "%s.config";
    private static final String TEST_STUB = "TestStub"; // Trivial test stub
    private static final String TEST_STUB_SHARDABLE = "TestStubShardable";
    private static final String COMMAND_LINE = "run cts";

    private CompatibilityTest mTest;
    private ResultReporter mReporter;
    private ITestDevice mMockDevice;
    private IBuildInfo mMockBuildInfo;
    private IInvocationContext mContext;

    private File mRootDir;
    private File mAndroidFolder;
    private File mTestDir;
    private Map<String, String> mAttributes;

    @Before
    public void setUp() throws IOException {
        mAttributes = new HashMap<>();
        mTest = new CompatibilityTest() {
            @Override
            protected Set<String> getAbisForBuildTargetArch() {
                Set<String> abis = new HashSet<>();
                abis.add("arm64-v8a");
                abis.add("armeabi-v7a");
                return abis;
            }
        };
        mReporter = new ResultReporter();
        mMockDevice = EasyMock.createMock(ITestDevice.class);
        mMockBuildInfo = EasyMock.createMock(IBuildInfo.class);
        mTest.setBuild(mMockBuildInfo);
        mTest.setDevice(mMockDevice);
        mRootDir = FileUtil.createTempDir("fake-cts-root-dir");
        mAndroidFolder = FileUtil.createTempDir("android-", mRootDir);
        mTestDir = new File(mAndroidFolder, "testcases");
        mTestDir.mkdirs();
        String suiteName = mAndroidFolder.getName().split("-")[1];
        // Create fake build attributes
        mAttributes.put(CompatibilityBuildHelper.ROOT_DIR, mRootDir.getAbsolutePath());
        mAttributes.put(CompatibilityBuildHelper.SUITE_NAME, suiteName);
        mAttributes.put(CompatibilityBuildHelper.START_TIME_MS, "0");
        mAttributes.put(CompatibilityBuildHelper.SUITE_VERSION, "10");
        mAttributes.put(CompatibilityBuildHelper.SUITE_PLAN, "cts");
        mAttributes.put(CompatibilityBuildHelper.SUITE_BUILD, "good-build");
        mAttributes.put(CompatibilityBuildHelper.COMMAND_LINE_ARGS, COMMAND_LINE);

        // these attributes seems necessary for re-run, not for run
        mAttributes.put("cts:build_fingerprint", "fingerprint");
        mAttributes.put("cts:build_product", "product");
        mAttributes.put("cts:build_id", "bid");

        EasyMock.expect(mMockBuildInfo.getBuildAttributes()).andStubReturn(mAttributes);

        EasyMock.expect(mMockDevice.getSerialNumber()).andStubReturn("SERIAL");
        EasyMock.expect(mMockBuildInfo.getDeviceSerial()).andStubReturn("SERIAL");

        mContext = new InvocationContext();
        mContext.addAllocatedDevice("default", mMockDevice);
        mContext.addDeviceBuildInfo("default", mMockBuildInfo);
    }

    @After
    public void tearDown() {
        FileUtil.recursiveDelete(mRootDir);
    }

    /**
     * Create a CTS configuration with a fake tests to exercise all cases.
     *
     * @param testsDir The testcases/ dir where to put the module
     * @param name the name of the module.
     * @param moduleClass the fake test class to use.
     * @param reportTest True if the test report some tests
     * @param runComplete True if the test run is complete
     * @param doesOneTestFail True if one of the test is going to fail
     * @param internalRetry True if the test will retry the module itself once
     */
    private void createConfig(File testsDir, String name, String moduleClass, boolean reportTest,
            boolean runComplete, boolean doesOneTestFail, boolean internalRetry)
                    throws IOException {
        File config = new File(testsDir, String.format(FILENAME, name));
        FileUtil.deleteFile(config);
        if (!config.createNewFile()) {
            throw new IOException(String.format("Failed to create '%s'", config.getAbsolutePath()));
        }

        FileUtil.writeToFile(String.format(CONFIG, moduleClass, reportTest, runComplete,
                doesOneTestFail, internalRetry), config);
    }

    /**
     * Simple tests running in one module that should be marked complete.
     */
    @Test
    public void testSingleModuleRun() throws Exception {
        final String moduleName = "module_run";
        final String mAbi = "arm64-v8a";
        createConfig(mTestDir, moduleName, TEST_STUB, true, true, true, false);
        EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);

        mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
                EasyMock.eq(AbiUtils.createId(mAbi, moduleName)));
        EasyMock.expectLastCall();

        EasyMock.replay(mMockDevice, mMockBuildInfo);
        mReporter.invocationStarted(mContext);
        mTest.run(mReporter);
        mReporter.invocationEnded(500);
        EasyMock.verify(mMockDevice, mMockBuildInfo);
        IInvocationResult result = mReporter.getResult();
        assertEquals(2, result.countResults(TestStatus.PASS));
        assertEquals(1, result.countResults(TestStatus.FAIL));
        assertEquals(1, result.getModules().size());
        assertEquals(1, result.getModuleCompleteCount());
    }

    /**
     * Simple tests running in one module that run some tests but not all of them.
     */
    @Test
    public void testSingleModuleRun_incomplete() throws Exception {
        final String moduleName = "module_run_incomplete";
        final String mAbi = "arm64-v8a";
        createConfig(mTestDir, moduleName, TEST_STUB, true, false, true, false);
        EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);

        mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
                EasyMock.eq(AbiUtils.createId(mAbi, moduleName)));
        EasyMock.expectLastCall();

        EasyMock.replay(mMockDevice, mMockBuildInfo);
        mReporter.invocationStarted(mContext);
        mTest.run(mReporter);
        mReporter.invocationEnded(500);
        EasyMock.verify(mMockDevice, mMockBuildInfo);
        IInvocationResult result = mReporter.getResult();
        assertEquals(1, result.countResults(TestStatus.PASS));
        assertEquals(1, result.countResults(TestStatus.FAIL));
        // Module should not be seen as complete.
        assertEquals(1, result.getModules().size());
        assertEquals(0, result.getModuleCompleteCount());
    }

    /**
     * Simple tests running in one module that should be marked complete since it runs all its
     * tests after an internal retry (like InstrumentationTest).
     * FIXME: Fix the expectation of this test
     */
    @Test
    public void testSingleModuleRun_completeAfterInternalRetry() throws Exception {
        final String moduleName = "module_completeAfterRetry";
        final String mAbi = "arm64-v8a";
        createConfig(mTestDir, moduleName, TEST_STUB, true, true, true, true);
        EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);

        mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
                EasyMock.eq(AbiUtils.createId(mAbi, moduleName)));
        EasyMock.expectLastCall();

        EasyMock.replay(mMockDevice, mMockBuildInfo);
        mReporter.invocationStarted(mContext);
        mTest.run(mReporter);
        mReporter.invocationEnded(500);
        EasyMock.verify(mMockDevice, mMockBuildInfo);
        IInvocationResult result = mReporter.getResult();
        // FIXME: All tests should be marked as executed and not aggregating the count.
        assertEquals(2, result.countResults(TestStatus.PASS));
        assertEquals(1, result.countResults(TestStatus.FAIL));
        // FIXME: Module should be complete since all its test have run.
        assertEquals(1, result.getModules().size());
        assertEquals(0, result.getModuleCompleteCount());
    }

    /**
     * Simple tests running in one module that run some tests but not all of them, then we
     * attempt to run it again and they still didn't run.
     * FIXME: This test expectation needs to be fixed
     */
    @Test
    public void testSingleModuleRun_incomplete_rerun_incomplete() throws Exception {
        final String moduleName = "module_incomplete_rerun";
        final String mAbi = "arm64-v8a";
        createConfig(mTestDir, moduleName, TEST_STUB, true, false, true, false);
        EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);

        mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
                EasyMock.eq(AbiUtils.createId(mAbi, moduleName)));
        EasyMock.expectLastCall();

        // extra calls for retry
        EasyMock.expect(mMockDevice.getProperty("ro.build.fingerprint")).andReturn("fingerprint");
        EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);
        mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
                EasyMock.eq(AbiUtils.createId(mAbi, moduleName)));
        EasyMock.expectLastCall();
        mMockBuildInfo.addBuildAttribute(EasyMock.eq("retry_command_line_args"),
                EasyMock.eq(COMMAND_LINE));
        EasyMock.expectLastCall();

        EasyMock.replay(mMockDevice, mMockBuildInfo);
        mReporter.invocationStarted(mContext);
        mTest.run(mReporter);
        mReporter.invocationEnded(500);

        IInvocationResult result = mReporter.getResult();
        assertEquals(1, result.countResults(TestStatus.PASS));
        assertEquals(1, result.countResults(TestStatus.FAIL));
        // Module should not be seen as complete.
        assertEquals(0, result.getModuleCompleteCount());

        // We re-run it
        mReporter = new ResultReporter();
        mTest = new CompatibilityTest() {
            @Override
            protected Set<String> getAbisForBuildTargetArch() {
                Set<String> abis = new HashSet<>();
                abis.add("arm64-v8a");
                return abis;
            }
        };
        mTest.setDevice(mMockDevice);
        mTest.setBuild(mMockBuildInfo);
        OptionSetter setter = new OptionSetter(mTest, mReporter);
        setter.setOptionValue("retry", "0");

        mReporter.invocationStarted(mContext);
        mTest.run(mReporter);
        mReporter.invocationEnded(500);
        EasyMock.verify(mMockDevice, mMockBuildInfo);

        // Check retry results
        result = mReporter.getResult();
        // FIXME: We should only have 1 not_executed in the retry too. They should not aggregate
        // from one run to another.
        assertEquals(1, result.countResults(TestStatus.PASS));
        assertEquals(1, result.countResults(TestStatus.FAIL));
        // Module should not be seen as complete.
        assertEquals(1, result.getModules().size());
        assertEquals(0, result.getModuleCompleteCount());
    }

    /**
     * Simple tests running in one module that run some tests but not all of them, we then attempt
     * to retry run them and this time the not_executed is executed.
     */
    @Test
    public void testSingleModuleRun_incomplete_rerun_complete() throws Exception {
        final String moduleName = "module_incom_rerun_complete";
        final String mAbi = "arm64-v8a";
        createConfig(mTestDir, moduleName, TEST_STUB, true, false, true, false);
        EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);

        mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
                EasyMock.eq(AbiUtils.createId(mAbi, moduleName)));
        EasyMock.expectLastCall();

        // extra calls for retry
        EasyMock.expect(mMockDevice.getProperty("ro.build.fingerprint")).andReturn("fingerprint");
        EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);
        mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
                EasyMock.eq(AbiUtils.createId(mAbi, moduleName)));
        EasyMock.expectLastCall();
        mMockBuildInfo.addBuildAttribute(EasyMock.eq("retry_command_line_args"),
                EasyMock.eq(COMMAND_LINE));
        EasyMock.expectLastCall();

        EasyMock.replay(mMockDevice, mMockBuildInfo);
        mReporter.invocationStarted(mContext);
        mTest.run(mReporter);
        mReporter.invocationEnded(500);

        IInvocationResult result = mReporter.getResult();
        assertEquals(1, result.countResults(TestStatus.PASS));
        assertEquals(1, result.countResults(TestStatus.FAIL));
        // Module should not be seen as complete.
        assertEquals(0, result.getModuleCompleteCount());

        // We replace the config by one that runs all tests without failures.
        createConfig(mTestDir, moduleName, TEST_STUB, true, true, false, false);
        // Usually configs do not change during the same session so we clear the map to have
        // the new version of the config.
        ((ConfigurationFactory)ConfigurationFactory.getInstance()).clearMapConfig();

        // We re-run it
        mReporter = new ResultReporter();
        mTest = new CompatibilityTest() {
            @Override
            protected Set<String> getAbisForBuildTargetArch() {
                Set<String> abis = new HashSet<>();
                abis.add("arm64-v8a");
                return abis;
            }
        };
        mTest.setDevice(mMockDevice);
        mTest.setBuild(mMockBuildInfo);
        OptionSetter setter = new OptionSetter(mTest, mReporter);
        setter.setOptionValue("retry", "0");

        mReporter.invocationStarted(mContext);
        mTest.run(mReporter);
        mReporter.invocationEnded(500);
        EasyMock.verify(mMockDevice, mMockBuildInfo);

        // Check retry results
        result = mReporter.getResult();
        assertEquals(3, result.countResults(TestStatus.PASS));
        assertEquals(0, result.countResults(TestStatus.FAIL));
        // Module should be marked as complete after retry.
        assertEquals(1, result.getModules().size());
        assertEquals(1, result.getModuleCompleteCount());
    }

    // ***** Case for sharding interaction *****

    /**
     * Helper to create a shard listener with the original reporter as master.
     */
    private ITestInvocationListener getShardListener(ResultReporter masterReporter) {
        List<ITestInvocationListener> shardListeners = new ArrayList<ITestInvocationListener>();
        ShardListener origConfigListener = new ShardListener(masterReporter);
        ResultReporter reporterClone = (ResultReporter) masterReporter.clone();
        shardListeners.add(reporterClone);
        shardListeners.add(origConfigListener);
        ResultForwarder shard = new ResultForwarder(shardListeners);
        return shard;
    }

    /**
     * Helper Thread to run the IShardableTest.
     */
    private class ShardThread extends Thread {
        private IRemoteTest mShardTest;
        private ResultReporter mMasterReporter;
        private IBuildInfo mBuild;
        private ITestDevice mDevice;
        private IInvocationContext mShardContext;

        public ShardThread(IRemoteTest test, ResultReporter masterReporter, IBuildInfo build,
                ITestDevice device, IInvocationContext context) {
            mShardTest = test;
            mMasterReporter = masterReporter;
            mBuild = build;
            mDevice = device;
            mShardContext = context;
        }

        @Override
        public void run() {
            ITestInvocationListener listener = getShardListener(mMasterReporter);
            ((IBuildReceiver)mShardTest).setBuild(mBuild);
            ((IDeviceTest)mShardTest).setDevice(mDevice);
            listener.invocationStarted(mShardContext);
            try {
                mShardTest.run(listener);
            } catch (DeviceNotAvailableException e) {
                throw new RuntimeException(e);
            } finally {
                listener.invocationEnded(500);
            }
        }
    }

    /**
     * Simple tests running in one module that should be marked complete when each shard run a test
     * from the module. Each Module is going to run 1 pass 1 fail. 2 modules and 2 shards.
     * Using the {@link CompatibilityTest#split()}.
     */
    @Test
    public void testSingleModuleRun_sharded() throws Exception {
        final String moduleName = "module_sharded";
        Set<String> abis = AbiUtils.getAbisForArch(SuiteInfo.TARGET_ARCH);
        Iterator<String> ite = abis.iterator();
        final String abi1 = ite.next();
        final String abi2 = ite.next();
        createConfig(mTestDir, moduleName, TEST_STUB_SHARDABLE, true, true, true, false);
        EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(
                String.format("%s,%s", abi1, abi2));
        mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
                EasyMock.anyObject());
        EasyMock.expectLastCall();

        EasyMock.replay(mMockDevice, mMockBuildInfo);

        OptionSetter setter = new OptionSetter(mTest);
        setter.setOptionValue("shards", "2");
        List<IRemoteTest> tests = (List<IRemoteTest>) mTest.split();
        // We expect 2 shards
        assertEquals(2, tests.size());

        List<ShardThread> threads = new ArrayList<>();
        // Run all shards
        for (IRemoteTest test : tests) {
            ShardThread st = new ShardThread(test, mReporter, mMockBuildInfo, mMockDevice,
                    mContext);
            threads.add(st);
            st.start();
        }
        for (ShardThread thread : threads) {
            thread.join(5000);
        }
        // Allow some time for ResultReport to finalize the results coming from the threads.
        boolean finalized = mReporter.waitForFinalized(2, TimeUnit.MINUTES);
        assertTrue(finalized);
        EasyMock.verify(mMockDevice, mMockBuildInfo);
        // Check aggregated results to make sure it's consistent.
        IInvocationResult result = mReporter.getResult();
        assertEquals(4, result.countResults(TestStatus.PASS));
        assertEquals(4, result.countResults(TestStatus.FAIL));
        assertEquals(2, result.getModules().size());
        assertEquals(2, result.getModuleCompleteCount());
    }

    /**
     * Simple tests running in one module that should be marked incomplete when shards do not
     * complete. Each shard is going to run 1 pass 1 fail 1 not_executed.
     * Using the {@link CompatibilityTest#split()}.
     */
    @Test
    public void testSingleModuleRun_sharded_incomplete() throws Exception {
        final String moduleName = "module_sharded_incomplete";
        Set<String> abis = AbiUtils.getAbisForArch(SuiteInfo.TARGET_ARCH);
        Iterator<String> ite = abis.iterator();
        final String abi1 = ite.next();
        final String abi2 = ite.next();
        createConfig(mTestDir, moduleName, TEST_STUB_SHARDABLE, true, false, true, false);
        EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(
                String.format("%s,%s", abi1, abi2));
        mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
                EasyMock.anyObject());
        EasyMock.expectLastCall();

        EasyMock.replay(mMockDevice, mMockBuildInfo);
        OptionSetter setter = new OptionSetter(mTest);
        setter.setOptionValue("shards", "2");
        List<IRemoteTest> tests = (List<IRemoteTest>) mTest.split();
        // We expect 2 shards
        assertEquals(2, tests.size());

        List<ShardThread> threads = new ArrayList<>();
        // Run all shards
        for (IRemoteTest test : tests) {
            ShardThread st = new ShardThread(test, mReporter, mMockBuildInfo, mMockDevice,
                    mContext);
            threads.add(st);
            st.start();
        }
        for (ShardThread thread : threads) {
            thread.join(5000);
        }
        // Allow some time for ResultReport to finalize the results coming from the threads.
        boolean finalized = mReporter.waitForFinalized(2, TimeUnit.MINUTES);
        assertTrue(finalized);
        EasyMock.verify(mMockDevice, mMockBuildInfo);
        // Check aggregated results to make sure it's consistent.
        IInvocationResult result = mReporter.getResult();
        assertEquals(4, result.countResults(TestStatus.PASS));
        assertEquals(4, result.countResults(TestStatus.FAIL));
        assertEquals(2, result.getModules().size());
        assertEquals(0, result.getModuleCompleteCount());
    }

    /**
     * Simple tests running in one module that should be marked complete when each shard run a test
     * from the module.
     * We are going to run only one of the shard since IStrictShardable allows it.
     * Using the {@link CompatibilityTest#getTestShard(int, int)}.
     * FIXME: Fix expectation of this test.
     */
    @Test
    public void testSingleModuleRun_sharded_getTestShard() throws Exception {
        final String moduleName = "module_sharded_getTestShard";
        Set<String> abis = AbiUtils.getAbisForArch(SuiteInfo.TARGET_ARCH);
        Iterator<String> ite = abis.iterator();
        final String abi1 = ite.next();
        final String abi2 = ite.next();
        createConfig(mTestDir, moduleName, TEST_STUB_SHARDABLE, true, true, true, false);
        EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(
                String.format("%s,%s", abi1, abi2));

        String expectedAdd = AbiUtils.createId(abi1, moduleName) + ","
                + AbiUtils.createId(abi2, moduleName);
        mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
                EasyMock.anyObject());
        EasyMock.expectLastCall();
        mAttributes.put(CompatibilityBuildHelper.MODULE_IDS, expectedAdd);

        EasyMock.replay(mMockDevice, mMockBuildInfo);

        List<IRemoteTest> tests = new ArrayList<>();
        tests.add(mTest.getTestShard(3, 0));
        // We are only running one of the shards since they should be independent.
        assertEquals(1, tests.size());

        ((IBuildReceiver)tests.get(0)).setBuild(mMockBuildInfo);
        ((IDeviceTest)tests.get(0)).setDevice(mMockDevice);
        mReporter.invocationStarted(mContext);
        try {
            tests.get(0).run(mReporter);
        } catch (DeviceNotAvailableException e) {
            throw new RuntimeException(e);
        } finally {
            mReporter.invocationEnded(500);
        }
        EasyMock.verify(mMockDevice, mMockBuildInfo);

        IInvocationResult result = mReporter.getResult();
        assertEquals(2, result.countResults(TestStatus.PASS));
        assertEquals(2, result.countResults(TestStatus.FAIL));
        // FIXME: Only one module should be expected since within the one shard requested to run
        // only one module existed.
        assertEquals(2, result.getModules().size());
        // FIXME: The module for the shard should be completed since all tests run.
        // TestRunHandler in this case create an expectation of 3 testRunStarted just because of
        // the number of shards.
        assertEquals(0, result.getModuleCompleteCount());
    }
}
