Home | History | Annotate | Download | only in shard
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.tradefed.invoker.shard;
     17 
     18 import static org.junit.Assert.assertEquals;
     19 import static org.junit.Assert.assertNotNull;
     20 import static org.junit.Assert.assertNull;
     21 import static org.junit.Assert.assertTrue;
     22 import static org.junit.Assert.fail;
     23 
     24 import com.android.tradefed.config.OptionSetter;
     25 import com.android.tradefed.device.DeviceNotAvailableException;
     26 import com.android.tradefed.device.DeviceUnresponsiveException;
     27 import com.android.tradefed.device.ITestDevice;
     28 import com.android.tradefed.device.metric.IMetricCollector;
     29 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
     30 import com.android.tradefed.result.ITestInvocationListener;
     31 import com.android.tradefed.testtype.IRemoteTest;
     32 import com.android.tradefed.testtype.StubTest;
     33 
     34 import org.junit.Before;
     35 import org.junit.Test;
     36 import org.junit.runner.RunWith;
     37 import org.junit.runners.JUnit4;
     38 import org.mockito.Mockito;
     39 
     40 import java.util.ArrayList;
     41 import java.util.HashMap;
     42 import java.util.List;
     43 import java.util.concurrent.CountDownLatch;
     44 
     45 /** Unit tests for {@link TestsPoolPoller}. */
     46 @RunWith(JUnit4.class)
     47 public class TestsPoolPollerTest {
     48 
     49     private ITestInvocationListener mListener;
     50     private ITestDevice mDevice;
     51     private List<IMetricCollector> mMetricCollectors;
     52 
     53     @Before
     54     public void setUp() {
     55         mListener = Mockito.mock(ITestInvocationListener.class);
     56         mDevice = Mockito.mock(ITestDevice.class);
     57         Mockito.doReturn("serial").when(mDevice).getSerialNumber();
     58         mMetricCollectors = new ArrayList<>();
     59     }
     60 
     61     /**
     62      * Tests that {@link TestsPoolPoller#poll()} returns a {@link IRemoteTest} from the pool or null
     63      * when the pool is empty.
     64      */
     65     @Test
     66     public void testMultiPolling() {
     67         int numTests = 5;
     68         List<IRemoteTest> testsList = new ArrayList<>();
     69         for (int i = 0; i < numTests; i++) {
     70             testsList.add(new StubTest());
     71         }
     72         CountDownLatch tracker = new CountDownLatch(2);
     73         TestsPoolPoller poller1 = new TestsPoolPoller(testsList, tracker);
     74         TestsPoolPoller poller2 = new TestsPoolPoller(testsList, tracker);
     75         // initial size
     76         assertEquals(numTests, testsList.size());
     77         assertNotNull(poller1.poll());
     78         assertEquals(numTests - 1, testsList.size());
     79         assertNotNull(poller2.poll());
     80         assertEquals(numTests - 2, testsList.size());
     81         assertNotNull(poller1.poll());
     82         assertNotNull(poller1.poll());
     83         assertNotNull(poller2.poll());
     84         assertTrue(testsList.isEmpty());
     85         // once empty poller returns null
     86         assertNull(poller1.poll());
     87         assertNull(poller2.poll());
     88     }
     89 
     90     /**
     91      * Tests that {@link TestsPoolPoller#run(ITestInvocationListener)} is properly running and
     92      * redirecting the invocation callbacks.
     93      */
     94     @Test
     95     public void testPollingRun() throws Exception {
     96         int numTests = 5;
     97         List<IRemoteTest> testsList = new ArrayList<>();
     98         for (int i = 0; i < numTests; i++) {
     99             IRemoteTest test = new StubTest();
    100             OptionSetter setter = new OptionSetter(test);
    101             setter.setOptionValue("run-a-test", "true");
    102             testsList.add(test);
    103         }
    104         CountDownLatch tracker = new CountDownLatch(1);
    105         TestsPoolPoller poller = new TestsPoolPoller(testsList, tracker);
    106         poller.setMetricCollectors(mMetricCollectors);
    107         poller.run(mListener);
    108         Mockito.verify(mListener, Mockito.times(numTests))
    109                 .testRunStarted(Mockito.anyString(), Mockito.anyInt());
    110         Mockito.verify(mListener, Mockito.times(numTests))
    111                 .testRunEnded(Mockito.anyLong(), (HashMap<String, Metric>) Mockito.any());
    112         assertEquals(0, tracker.getCount());
    113     }
    114 
    115     /**
    116      * Tests that {@link TestsPoolPoller#run(ITestInvocationListener)} will continue to run tests
    117      * even if one of them throws a {@link RuntimeException}.
    118      */
    119     @Test
    120     public void testRun_runtimeException() throws Exception {
    121         List<IRemoteTest> testsList = new ArrayList<>();
    122         // Add one bad test first that will throw an exception.
    123         IRemoteTest badTest = new StubTest();
    124         OptionSetter setter = new OptionSetter(badTest);
    125         setter.setOptionValue("test-throw-runtime", "true");
    126         testsList.add(badTest);
    127         // Add tests that can run
    128         int numTests = 5;
    129         for (int i = 0; i < numTests; i++) {
    130             IRemoteTest test = new StubTest();
    131             OptionSetter s = new OptionSetter(test);
    132             s.setOptionValue("run-a-test", "true");
    133             testsList.add(test);
    134         }
    135         CountDownLatch tracker = new CountDownLatch(1);
    136         TestsPoolPoller poller = new TestsPoolPoller(testsList, tracker);
    137         poller.setMetricCollectors(mMetricCollectors);
    138         poller.run(mListener);
    139         Mockito.verify(mListener, Mockito.times(numTests))
    140                 .testRunStarted(Mockito.anyString(), Mockito.anyInt());
    141         Mockito.verify(mListener, Mockito.times(numTests))
    142                 .testRunEnded(Mockito.anyLong(), (HashMap<String, Metric>) Mockito.any());
    143         assertEquals(0, tracker.getCount());
    144     }
    145 
    146     /**
    147      * Tests that {@link TestsPoolPoller#run(ITestInvocationListener)} will continue to run tests
    148      * even if one of them throws a {@link DeviceUnresponsiveException}.
    149      */
    150     @Test
    151     public void testRun_deviceUnresponsive() throws Exception {
    152         List<IRemoteTest> testsList = new ArrayList<>();
    153         // Add one bad test first that will throw an exception.
    154         IRemoteTest badTest = new StubTest();
    155         OptionSetter setter = new OptionSetter(badTest);
    156         setter.setOptionValue("test-throw-unresponsive", "true");
    157         testsList.add(badTest);
    158         // Add tests that can run
    159         int numTests = 5;
    160         for (int i = 0; i < numTests; i++) {
    161             IRemoteTest test = new StubTest();
    162             OptionSetter s = new OptionSetter(test);
    163             s.setOptionValue("run-a-test", "true");
    164             testsList.add(test);
    165         }
    166         CountDownLatch tracker = new CountDownLatch(1);
    167         TestsPoolPoller poller = new TestsPoolPoller(testsList, tracker);
    168         poller.setMetricCollectors(mMetricCollectors);
    169         poller.run(mListener);
    170         Mockito.verify(mListener, Mockito.times(numTests))
    171                 .testRunStarted(Mockito.anyString(), Mockito.anyInt());
    172         Mockito.verify(mListener, Mockito.times(numTests))
    173                 .testRunEnded(Mockito.anyLong(), (HashMap<String, Metric>) Mockito.any());
    174         assertEquals(0, tracker.getCount());
    175     }
    176 
    177     /**
    178      * Tests that {@link TestsPoolPoller#run(ITestInvocationListener)} will stop to run tests if one
    179      * of them throws a {@link DeviceNotAvailableException}.
    180      */
    181     @Test
    182     public void testRun_dnae() throws Exception {
    183         List<IRemoteTest> testsList = new ArrayList<>();
    184         // Add one bad test first that will throw an exception.
    185         IRemoteTest badTest = new StubTest();
    186         OptionSetter setter = new OptionSetter(badTest);
    187         setter.setOptionValue("test-throw-not-available", "true");
    188         testsList.add(badTest);
    189         // Add tests that can run
    190         int numTests = 5;
    191         for (int i = 0; i < numTests; i++) {
    192             IRemoteTest test = new StubTest();
    193             OptionSetter s = new OptionSetter(test);
    194             s.setOptionValue("run-a-test", "true");
    195             testsList.add(test);
    196         }
    197         CountDownLatch tracker = new CountDownLatch(1);
    198         TestsPoolPoller poller = new TestsPoolPoller(testsList, tracker);
    199         poller.setMetricCollectors(mMetricCollectors);
    200         poller.setDevice(mDevice);
    201         try {
    202             poller.run(mListener);
    203             fail("Should have thrown an exception.");
    204         } catch (DeviceNotAvailableException expected) {
    205             // expected
    206         }
    207         // We expect no callbacks on these, poller should stop early.
    208         Mockito.verify(mListener, Mockito.times(0))
    209                 .testRunStarted(Mockito.anyString(), Mockito.anyInt());
    210         Mockito.verify(mListener, Mockito.times(0))
    211                 .testRunEnded(Mockito.anyLong(), (HashMap<String, Metric>) Mockito.any());
    212         assertEquals(0, tracker.getCount());
    213     }
    214 
    215     /**
    216      * If a device not available exception is thrown from a tests, and the poller is not the last
    217      * one alive, we wait and attempt to recover the device. In case of success, execution will
    218      * proceed.
    219      */
    220     @Test
    221     public void testRun_dnae_NotLastDevice() throws Exception {
    222         List<IRemoteTest> testsList = new ArrayList<>();
    223         // Add one bad test first that will throw an exception.
    224         IRemoteTest badTest = new StubTest();
    225         OptionSetter setter = new OptionSetter(badTest);
    226         setter.setOptionValue("test-throw-not-available", "true");
    227         testsList.add(badTest);
    228         // Add tests that can run
    229         int numTests = 5;
    230         for (int i = 0; i < numTests; i++) {
    231             IRemoteTest test = new StubTest();
    232             OptionSetter s = new OptionSetter(test);
    233             s.setOptionValue("run-a-test", "true");
    234             testsList.add(test);
    235         }
    236         CountDownLatch tracker = new CountDownLatch(3);
    237         TestsPoolPoller poller = new TestsPoolPoller(testsList, tracker);
    238         poller.setMetricCollectors(mMetricCollectors);
    239         poller.setDevice(mDevice);
    240 
    241         poller.run(mListener);
    242         // The callbacks from all the other tests because the device was recovered
    243         Mockito.verify(mListener, Mockito.times(numTests))
    244                 .testRunStarted(Mockito.anyString(), Mockito.anyInt());
    245         Mockito.verify(mListener, Mockito.times(numTests)).testStarted(Mockito.any());
    246         Mockito.verify(mListener, Mockito.times(numTests))
    247                 .testEnded(Mockito.any(), (HashMap<String, Metric>) Mockito.any());
    248         Mockito.verify(mListener, Mockito.times(numTests))
    249                 .testRunEnded(Mockito.anyLong(), (HashMap<String, Metric>) Mockito.any());
    250         Mockito.verify(mDevice).waitForDeviceAvailable(Mockito.anyLong());
    251         Mockito.verify(mDevice).reboot();
    252         assertEquals(2, tracker.getCount());
    253     }
    254 }
    255