Home | History | Annotate | Download | only in collectors
      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 android.device.collectors;
     17 
     18 import android.app.Instrumentation;
     19 import android.device.collectors.annotations.MetricOption;
     20 import android.device.collectors.annotations.OptionClass;
     21 import android.device.collectors.util.SendToInstrumentation;
     22 import android.os.Bundle;
     23 import android.support.test.runner.AndroidJUnit4;
     24 
     25 import org.junit.Before;
     26 import org.junit.Test;
     27 import org.junit.runner.Description;
     28 import org.junit.runner.Result;
     29 import org.junit.runner.RunWith;
     30 import org.mockito.ArgumentCaptor;
     31 import org.mockito.Mockito;
     32 
     33 import java.lang.annotation.Annotation;
     34 import java.util.List;
     35 
     36 import static org.junit.Assert.assertEquals;
     37 import static org.junit.Assert.assertFalse;
     38 import static org.junit.Assert.assertTrue;
     39 
     40 /**
     41  * Android Unit Tests for {@link BaseMetricListener}.
     42  */
     43 @RunWith(AndroidJUnit4.class)
     44 public class BaseMetricListenerInstrumentedTest {
     45 
     46     private static final String RUN_START_KEY = "run_start_key";
     47     private static final String RUN_END_KEY = "run_end_key";
     48     private static final String RUN_START_VALUE = "run_start_value";
     49     private static final String RUN_END_VALUE = "run_end_value";
     50     private static final String TEST_START_KEY = "test_start_key";
     51     private static final String TEST_END_KEY = "test_end_key";
     52     private static final String TEST_START_VALUE = "test_start_value";
     53     private static final String TEST_END_VALUE = "test_end_value";
     54     private BaseMetricListener mListener;
     55     private Instrumentation mMockInstrumentation;
     56 
     57     @Before
     58     public void setUp() {
     59         mMockInstrumentation = Mockito.mock(Instrumentation.class);
     60         mListener = createWithArgs(null);
     61         mListener.setInstrumentation(mMockInstrumentation);
     62     }
     63 
     64     private BaseMetricListener createWithArgs(Bundle args) {
     65         if (args == null) {
     66             args = new Bundle();
     67         }
     68         return new BaseMetricListener(args) {
     69             @Override
     70             public void onTestStart(DataRecord testData, Description description) {
     71                 // In this test check that a new DataRecord is passed to testStart each time.
     72                 assertFalse(testData.hasMetrics());
     73                 testData.addStringMetric(TEST_START_KEY, TEST_START_VALUE
     74                         + description.getMethodName());
     75             }
     76 
     77             @Override
     78             public void onTestEnd(DataRecord testData, Description description) {
     79                 testData.addStringMetric(TEST_END_KEY, TEST_END_VALUE
     80                         + description.getMethodName());
     81             }
     82 
     83             @Override
     84             public void onTestRunStart(DataRecord runData, Description description) {
     85                 assertFalse(runData.hasMetrics());
     86                 runData.addStringMetric(RUN_START_KEY, RUN_START_VALUE);
     87             }
     88 
     89             @Override
     90             public void onTestRunEnd(DataRecord runData, Result result) {
     91                 runData.addStringMetric(RUN_END_KEY, RUN_END_VALUE);
     92             }
     93         };
     94     }
     95 
     96     /**
     97      * When metrics are logged during a test, expect them to be added to the bundle.
     98      */
     99     @MetricOption(group = "testGroup,testGroup1")
    100     @Test
    101     public void testReportMetrics() throws Exception {
    102         Description runDescription = Description.createSuiteDescription("run");
    103         mListener.testRunStarted(runDescription);
    104         Description testDescription = Description.createTestDescription("class", "method");
    105         mListener.testStarted(testDescription);
    106         mListener.testFinished(testDescription);
    107         mListener.testRunFinished(new Result());
    108         // AJUR runner is then gonna call instrumentationRunFinished
    109         Bundle resultBundle = new Bundle();
    110         mListener.instrumentationRunFinished(System.out, resultBundle, new Result());
    111 
    112         // Check that the in progress status contains the metrics.
    113         ArgumentCaptor<Bundle> capture = ArgumentCaptor.forClass(Bundle.class);
    114         Mockito.verify(mMockInstrumentation)
    115                 .sendStatus(Mockito.eq(
    116                         SendToInstrumentation.INST_STATUS_IN_PROGRESS), capture.capture());
    117         List<Bundle> capturedBundle = capture.getAllValues();
    118         assertEquals(1, capturedBundle.size());
    119         Bundle check = capturedBundle.get(0);
    120         assertEquals(TEST_START_VALUE + "method", check.getString(TEST_START_KEY));
    121         assertEquals(TEST_END_VALUE + "method", check.getString(TEST_END_KEY));
    122         assertEquals(2, check.size());
    123 
    124         // Check that final bundle contains run results
    125         assertEquals(RUN_START_VALUE, resultBundle.getString(RUN_START_KEY));
    126         assertEquals(RUN_END_VALUE, resultBundle.getString(RUN_END_KEY));
    127         assertEquals(2, resultBundle.size());
    128     }
    129 
    130     /**
    131      * Test that only included group are running collection.
    132      */
    133     @MetricOption(group = "testGroup")
    134     @Test
    135     public void testReportMetrics_withIncludeFilters() throws Exception {
    136         Bundle args = new Bundle();
    137         args.putString(BaseMetricListener.INCLUDE_FILTER_GROUP_KEY, "group1,group2");
    138         mListener = createWithArgs(args);
    139         mListener.setInstrumentation(mMockInstrumentation);
    140 
    141         Description runDescription = Description.createSuiteDescription("run");
    142         mListener.testRunStarted(runDescription);
    143         Description testDescription = Description.createTestDescription("class", "method",
    144                 new TestAnnotation("group1"));
    145         mListener.testStarted(testDescription);
    146         mListener.testFinished(testDescription);
    147         // A second test case that will not be included
    148         Description testDescription2 = Description.createTestDescription("class", "method2",
    149                 new TestAnnotation("group3"));
    150         mListener.testStarted(testDescription2);
    151         mListener.testFinished(testDescription2);
    152         // A third test case that will be included
    153         Description testDescription3 = Description.createTestDescription("class", "method3",
    154                 new TestAnnotation("group2"));
    155         mListener.testStarted(testDescription3);
    156         mListener.testFinished(testDescription3);
    157 
    158         // Check that the in progress status contains the metrics.
    159         ArgumentCaptor<Bundle> capture = ArgumentCaptor.forClass(Bundle.class);
    160         Mockito.verify(mMockInstrumentation, Mockito.times(2))
    161                 .sendStatus(Mockito.eq(
    162                         SendToInstrumentation.INST_STATUS_IN_PROGRESS), capture.capture());
    163         // Check that only method2 did not generate any metrics since it was filtered.
    164         List<Bundle> capturedBundle = capture.getAllValues();
    165         assertEquals(2, capturedBundle.size());
    166         Bundle check = capturedBundle.get(0);
    167         assertEquals(TEST_START_VALUE + "method", check.getString(TEST_START_KEY));
    168         assertEquals(TEST_END_VALUE + "method", check.getString(TEST_END_KEY));
    169         assertEquals(2, check.size());
    170         // Got a call from the method3
    171         Bundle check2 = capturedBundle.get(1);
    172         assertEquals(TEST_START_VALUE + "method3", check2.getString(TEST_START_KEY));
    173         assertEquals(TEST_END_VALUE + "method3", check2.getString(TEST_END_KEY));
    174         assertEquals(2, check2.size());
    175     }
    176 
    177     /**
    178      * Test that only included group are running collection, even if some method have multiple
    179      * groups, if any of its group is included, the method is included.
    180      */
    181     @MetricOption(group = "testGroup")
    182     @Test
    183     public void testReportMetrics_withIncludeFilters_multiGroup() throws Exception {
    184         Bundle args = new Bundle();
    185         args.putString(BaseMetricListener.INCLUDE_FILTER_GROUP_KEY, "group4");
    186         mListener = createWithArgs(args);
    187         mListener.setInstrumentation(mMockInstrumentation);
    188 
    189         Description runDescription = Description.createSuiteDescription("run");
    190         mListener.testRunStarted(runDescription);
    191         Description testDescription = Description.createTestDescription("class", "method",
    192                 new TestAnnotation("group1"));
    193         mListener.testStarted(testDescription);
    194         mListener.testFinished(testDescription);
    195         // A second test case that will not be included
    196         Description testDescription2 = Description.createTestDescription("class", "method2",
    197                 new TestAnnotation("group3,group4"));
    198         mListener.testStarted(testDescription2);
    199         mListener.testFinished(testDescription2);
    200         // A third test case that will be included
    201         Description testDescription3 = Description.createTestDescription("class", "method3",
    202                 new TestAnnotation("group2"));
    203         mListener.testStarted(testDescription3);
    204         mListener.testFinished(testDescription3);
    205 
    206         // Check that the in progress status contains the metrics.
    207         ArgumentCaptor<Bundle> capture = ArgumentCaptor.forClass(Bundle.class);
    208         Mockito.verify(mMockInstrumentation, Mockito.times(1))
    209                 .sendStatus(Mockito.eq(
    210                         SendToInstrumentation.INST_STATUS_IN_PROGRESS), capture.capture());
    211         // Check that only method2 did generate metrics since it was included.
    212         List<Bundle> capturedBundle = capture.getAllValues();
    213         assertEquals(1, capturedBundle.size());
    214         Bundle check = capturedBundle.get(0);
    215         // Got call from method2
    216         assertEquals(TEST_START_VALUE + "method2", check.getString(TEST_START_KEY));
    217         assertEquals(TEST_END_VALUE + "method2", check.getString(TEST_END_KEY));
    218         assertEquals(2, check.size());
    219     }
    220 
    221     /**
    222      * Test that only not excluded group are running collection.
    223      */
    224     @MetricOption(group = "testGroup")
    225     @Test
    226     public void testReportMetrics_withExcludeFilters() throws Exception {
    227         Bundle args = new Bundle();
    228         args.putString(BaseMetricListener.EXCLUDE_FILTER_GROUP_KEY, "group1,group2");
    229         mListener = createWithArgs(args);
    230         mListener.setInstrumentation(mMockInstrumentation);
    231 
    232         Description runDescription = Description.createSuiteDescription("run");
    233         mListener.testRunStarted(runDescription);
    234         // A first test case that will not be included
    235         Description testDescription = Description.createTestDescription("class", "method",
    236                 new TestAnnotation("group1"));
    237         mListener.testStarted(testDescription);
    238         mListener.testFinished(testDescription);
    239         // A second test case that will run
    240         Description testDescription2 = Description.createTestDescription("class", "method2",
    241                 new TestAnnotation("group3"));
    242         mListener.testStarted(testDescription2);
    243         mListener.testFinished(testDescription2);
    244         // A third test case that will not be included
    245         Description testDescription3 = Description.createTestDescription("class", "method3",
    246                 new TestAnnotation("group2"));
    247         mListener.testStarted(testDescription3);
    248         mListener.testFinished(testDescription3);
    249 
    250         // Check that the in progress status contains the metrics.
    251         ArgumentCaptor<Bundle> capture = ArgumentCaptor.forClass(Bundle.class);
    252         Mockito.verify(mMockInstrumentation, Mockito.times(1))
    253                 .sendStatus(Mockito.eq(
    254                         SendToInstrumentation.INST_STATUS_IN_PROGRESS), capture.capture());
    255         // Check that only method2 generates some metrics
    256         List<Bundle> capturedBundle = capture.getAllValues();
    257         assertEquals(1, capturedBundle.size());
    258         Bundle check = capturedBundle.get(0);
    259         assertEquals(TEST_START_VALUE + "method2", check.getString(TEST_START_KEY));
    260         assertEquals(TEST_END_VALUE + "method2", check.getString(TEST_END_KEY));
    261         assertEquals(2, check.size());
    262     }
    263 
    264     /**
    265      * Test that when both filters are present, exclude filters have priority.
    266      */
    267     @MetricOption(group = "testGroup")
    268     @Test
    269     public void testReportMetrics_withBothFilters() throws Exception {
    270         Bundle args = new Bundle();
    271         args.putString(BaseMetricListener.EXCLUDE_FILTER_GROUP_KEY, "group1,group2");
    272         args.putString(BaseMetricListener.INCLUDE_FILTER_GROUP_KEY, "group2,group3");
    273         mListener = createWithArgs(args);
    274         mListener.setInstrumentation(mMockInstrumentation);
    275 
    276         Description runDescription = Description.createSuiteDescription("run");
    277         mListener.testRunStarted(runDescription);
    278         // A first test case that will not be included
    279         Description testDescription = Description.createTestDescription("class", "method",
    280                 new TestAnnotation("group1"));
    281         mListener.testStarted(testDescription);
    282         mListener.testFinished(testDescription);
    283         // A second test case that will run
    284         Description testDescription2 = Description.createTestDescription("class", "method2",
    285                 new TestAnnotation("group3"));
    286         mListener.testStarted(testDescription2);
    287         mListener.testFinished(testDescription2);
    288         // A third test case that will not be included
    289         Description testDescription3 = Description.createTestDescription("class", "method3",
    290                 new TestAnnotation("group2"));
    291         mListener.testStarted(testDescription3);
    292         mListener.testFinished(testDescription3);
    293 
    294         // Check that the in progress status contains the metrics.
    295         ArgumentCaptor<Bundle> capture = ArgumentCaptor.forClass(Bundle.class);
    296         Mockito.verify(mMockInstrumentation, Mockito.times(1))
    297                 .sendStatus(Mockito.eq(
    298                         SendToInstrumentation.INST_STATUS_IN_PROGRESS), capture.capture());
    299         // Check that only method2 generates some metrics
    300         List<Bundle> capturedBundle = capture.getAllValues();
    301         assertEquals(1, capturedBundle.size());
    302         Bundle check = capturedBundle.get(0);
    303         assertEquals(TEST_START_VALUE + "method2", check.getString(TEST_START_KEY));
    304         assertEquals(TEST_END_VALUE + "method2", check.getString(TEST_END_KEY));
    305         assertEquals(2, check.size());
    306     }
    307 
    308     /**
    309      * Test annotation that allows to instantiate {@link MetricOption} for testing purpose.
    310      */
    311     public static class TestAnnotation implements MetricOption {
    312         private String mGroup;
    313 
    314         public TestAnnotation(String group) {
    315             mGroup = group;
    316         }
    317 
    318         @Override
    319         public String group() {
    320             return mGroup;
    321         }
    322 
    323         @Override
    324         public Class<? extends Annotation> annotationType() {
    325             return MetricOption.class;
    326         }
    327     }
    328 
    329     /**
    330      * Test listener with an {@link OptionClass} specified to be used for arguments testing.
    331      */
    332     @OptionClass(alias = "test-alias-class")
    333     public static class TestListener extends BaseMetricListener {
    334 
    335         public TestListener(Bundle b) {
    336             super(b);
    337         }
    338     }
    339 
    340     /**
    341      * Test when the listener does not have an {@link OptionClass} specified, option with alias
    342      * are filtered.
    343      */
    344     @MetricOption(group = "testGroup")
    345     @Test
    346     public void testArgsAlias_noOptionClass() throws Exception {
    347         Bundle args = new Bundle();
    348         args.putString("optionalias:optionname", "optionvalue");
    349         args.putString("noalias", "noaliasvalue");
    350         mListener = createWithArgs(args);
    351         mListener.setInstrumentation(mMockInstrumentation);
    352         Description runDescription = Description.createSuiteDescription("run");
    353         mListener.testRunStarted(runDescription);
    354         Bundle filteredArgs = mListener.getArgsBundle();
    355         assertFalse(filteredArgs.containsKey("optionalias:optionname"));
    356         assertFalse(filteredArgs.containsKey("optionname"));
    357         assertTrue(filteredArgs.containsKey("noalias"));
    358     }
    359 
    360     /**
    361      * Test when a listener does have an {@link OptionClass} specified, in that case only options
    362      * matching the alias or with no alias are preserved.
    363      */
    364     @MetricOption(group = "testGroup")
    365     @Test
    366     public void testArgsAlias_optionClass() throws Exception {
    367         Bundle args = new Bundle();
    368         args.putString("test-alias-class:optionname", "optionvalue");
    369         args.putString("noalias", "noaliasvalue");
    370         args.putString("anotheralias:optionname2", "value");
    371         TestListener listener = new TestListener(args);
    372         listener.setInstrumentation(mMockInstrumentation);
    373         Description runDescription = Description.createSuiteDescription("run");
    374         listener.testRunStarted(runDescription);
    375         Bundle filteredArgs = listener.getArgsBundle();
    376         assertTrue(filteredArgs.containsKey("noalias"));
    377         assertTrue(filteredArgs.containsKey("optionname"));
    378 
    379         assertFalse(filteredArgs.containsKey("test-alias-class:optionname"));
    380         assertFalse(filteredArgs.containsKey("anotheralias:optionname2"));
    381         assertFalse(filteredArgs.containsKey("optionname2"));
    382     }
    383 }
    384