Home | History | Annotate | Download | only in metric
      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.device.metric;
     17 
     18 import static org.junit.Assert.assertEquals;
     19 import static org.junit.Assert.assertTrue;
     20 import static org.junit.Assert.fail;
     21 
     22 import com.android.tradefed.config.OptionSetter;
     23 import com.android.tradefed.device.ITestDevice;
     24 import com.android.tradefed.invoker.IInvocationContext;
     25 import com.android.tradefed.invoker.InvocationContext;
     26 import com.android.tradefed.metrics.proto.MetricMeasurement.Measurements;
     27 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
     28 import com.android.tradefed.result.ITestInvocationListener;
     29 import com.android.tradefed.util.RunUtil;
     30 
     31 import org.junit.Before;
     32 import org.junit.Rule;
     33 import org.junit.Test;
     34 import org.junit.rules.TemporaryFolder;
     35 import org.junit.runner.RunWith;
     36 import org.junit.runners.JUnit4;
     37 import org.mockito.Mock;
     38 import org.mockito.MockitoAnnotations;
     39 import org.mockito.Spy;
     40 
     41 import java.io.File;
     42 import java.util.ArrayList;
     43 import java.util.HashMap;
     44 import java.util.List;
     45 import java.util.Map;
     46 
     47 /** Unit tests for {@link ScheduleMultipleDeviceMetricCollector}. */
     48 @RunWith(JUnit4.class)
     49 public class ScheduleMultipleDeviceMetricCollectorTest {
     50     @Rule public final TemporaryFolder folder = new TemporaryFolder();
     51     @Mock private ITestDevice mTestDevice;
     52     @Mock private ITestInvocationListener mMockListener;
     53     @Spy private ScheduleMultipleDeviceMetricCollector mMultipleMetricCollector;
     54 
     55     private IInvocationContext mContext;
     56 
     57     static class TestMeminfoCollector extends ScheduledDeviceMetricCollector {
     58         private int mInternalCounter = 0;
     59         private String key = "meminfo";
     60 
     61         TestMeminfoCollector() {
     62             setTag("meminfoInterval");
     63         }
     64 
     65         @Override
     66         public void collect(ITestDevice device, DeviceMetricData runData)
     67                 throws InterruptedException {
     68             mInternalCounter++;
     69             runData.addMetricForDevice(
     70                     device,
     71                     key + mInternalCounter,
     72                     Metric.newBuilder()
     73                             .setMeasurements(
     74                                     Measurements.newBuilder()
     75                                             .setSingleString("value" + mInternalCounter)));
     76         }
     77     }
     78 
     79     static class TestJankinfoCollector extends ScheduledDeviceMetricCollector {
     80         private int mInternalCounter = 0;
     81         private String key = "jankinfo";
     82 
     83         TestJankinfoCollector() {
     84             setTag("jankInterval");
     85         }
     86 
     87         @Override
     88         public void collect(ITestDevice device, DeviceMetricData runData)
     89                 throws InterruptedException {
     90             mInternalCounter++;
     91             runData.addMetricForDevice(
     92                     device,
     93                     key + mInternalCounter,
     94                     Metric.newBuilder()
     95                             .setMeasurements(
     96                                     Measurements.newBuilder()
     97                                             .setSingleString("value" + mInternalCounter)));
     98         }
     99     }
    100 
    101     static class TestFragmentationCollector extends ScheduledDeviceMetricCollector {
    102         private int mInternalCounter = 0;
    103         private String key = "fragmentation";
    104 
    105         TestFragmentationCollector() {
    106             setTag("fragmentationInterval");
    107         }
    108 
    109         @Override
    110         public void collect(ITestDevice device, DeviceMetricData runData)
    111                 throws InterruptedException {
    112             mInternalCounter++;
    113             runData.addMetricForDevice(
    114                     device,
    115                     key + mInternalCounter,
    116                     Metric.newBuilder()
    117                             .setMeasurements(
    118                                     Measurements.newBuilder()
    119                                             .setSingleString("value" + mInternalCounter)));
    120         }
    121     }
    122 
    123     @Before
    124     public void setUp() throws Exception {
    125         MockitoAnnotations.initMocks(this);
    126         mContext = new InvocationContext();
    127         mContext.addAllocatedDevice("test device", mTestDevice);
    128     }
    129 
    130     @Test
    131     public void testMultipleMetricCollector_success() throws Exception {
    132         OptionSetter setter = new OptionSetter(mMultipleMetricCollector);
    133 
    134         // Set up the metric collection storage path.
    135         File metricStoragePath = folder.newFolder();
    136         setter.setOptionValue("metric-storage-path", metricStoragePath.toString());
    137 
    138         // Set up the intervals.
    139         Map<String, Long> intervals = new HashMap<>();
    140         intervals.put("meminfoInterval", 100L);
    141         intervals.put("fragmentationInterval", 100L);
    142         intervals.put("jankInterval", 100L);
    143         for (String key : intervals.keySet()) {
    144             setter.setOptionValue(
    145                     "metric-collection-intervals", key, intervals.get(key).toString());
    146         }
    147 
    148         // Request the collectors.
    149         List<String> classnames = new ArrayList<>();
    150         classnames.add(TestMeminfoCollector.class.getName());
    151         classnames.add(TestJankinfoCollector.class.getName());
    152         classnames.add(TestFragmentationCollector.class.getName());
    153         for (String key : classnames) {
    154             setter.setOptionValue("metric-collector-command-classes", key);
    155         }
    156 
    157         DeviceMetricData runData = new DeviceMetricData(mContext);
    158 
    159         // Start the tests.
    160         HashMap<String, Metric> metrics = new HashMap<>();
    161         mMultipleMetricCollector.init(mContext, mMockListener);
    162         try {
    163             mMultipleMetricCollector.onTestRunStart(runData);
    164             RunUtil.getDefault().sleep(500);
    165         } finally {
    166             mMultipleMetricCollector.onTestRunEnd(runData, metrics);
    167         }
    168 
    169         // We give it 500msec to run and 100msec interval we should easily have at least run all the
    170         // metrics once.
    171         // assert that the metrics contains filenames of all the collected metrics.
    172         HashMap<String, Metric> metricsCollected = new HashMap<>();
    173         runData.addToMetrics(metricsCollected);
    174 
    175         assertTrue(metricsCollected.containsKey("jankinfo1"));
    176         assertTrue(metricsCollected.containsKey("meminfo1"));
    177         assertTrue(metricsCollected.containsKey("fragmentation1"));
    178     }
    179 
    180     @Test
    181     public void testMultipleMetricCollector_noFailureEvenIfNoCollectorRequested() throws Exception {
    182         HashMap<String, Metric> metrics = new HashMap<>();
    183         mMultipleMetricCollector.init(mContext, mMockListener);
    184 
    185         DeviceMetricData runData = new DeviceMetricData(mContext);
    186 
    187         try {
    188             mMultipleMetricCollector.onTestRunStart(runData);
    189             RunUtil.getDefault().sleep(500);
    190         } finally {
    191             mMultipleMetricCollector.onTestRunEnd(runData, metrics);
    192         }
    193 
    194         // No metrics should have been collected.
    195         HashMap<String, Metric> metricsCollected = new HashMap<>();
    196         runData.addToMetrics(metricsCollected);
    197 
    198         assertEquals(0, metricsCollected.size());
    199     }
    200 
    201     /** Test that if a specified collector does not exists, we ignore it and proceed. */
    202     @Test
    203     public void testMultipleMetricCollector_collectorNotFound() throws Exception {
    204         OptionSetter setter = new OptionSetter(mMultipleMetricCollector);
    205 
    206         // Set up the metric collection storage path.
    207         File metricStoragePath = folder.newFolder();
    208         setter.setOptionValue("metric-storage-path", metricStoragePath.toString());
    209 
    210         // Set up the intervals.
    211         Map<String, Long> intervals = new HashMap<>();
    212         intervals.put("meminfoInterval", 100L);
    213         for (String key : intervals.keySet()) {
    214             setter.setOptionValue(
    215                     "metric-collection-intervals", key, intervals.get(key).toString());
    216         }
    217 
    218         // Request the collectors.
    219         List<String> classnames = new ArrayList<>();
    220         classnames.add(TestMeminfoCollector.class.getName());
    221         classnames.add("this.does.not.exists.collector");
    222         for (String key : classnames) {
    223             setter.setOptionValue("metric-collector-command-classes", key);
    224         }
    225 
    226         HashMap<String, Metric> metrics = new HashMap<>();
    227         mMultipleMetricCollector.init(mContext, mMockListener);
    228 
    229         DeviceMetricData runData = new DeviceMetricData(mContext);
    230 
    231         try {
    232             mMultipleMetricCollector.onTestRunStart(runData);
    233             RunUtil.getDefault().sleep(500);
    234         } finally {
    235             mMultipleMetricCollector.onTestRunEnd(runData, metrics);
    236         }
    237 
    238         // No metrics should have been collected.
    239         HashMap<String, Metric> metricsCollected = new HashMap<>();
    240         runData.addToMetrics(metricsCollected);
    241 
    242         assertTrue(metricsCollected.containsKey("meminfo1"));
    243     }
    244 
    245     @Test
    246     public void testMultipleMetricCollector_failsForNonNegativeInterval() throws Exception {
    247         String expectedStderr =
    248                 "class com.android.tradefed.device.metric."
    249                         + "ScheduleMultipleDeviceMetricCollectorTest$TestJankinfoCollector expects "
    250                         + "a non negative interval.";
    251 
    252         OptionSetter setter = new OptionSetter(mMultipleMetricCollector);
    253 
    254         // Set up the metric collection storage path.
    255         setter.setOptionValue("metric-storage-path", folder.newFolder().toString());
    256 
    257         // Set up the interval.
    258         Map<String, Long> intervals = new HashMap<>();
    259         intervals.put("jankInterval", -100L);
    260         for (String key : intervals.keySet()) {
    261             setter.setOptionValue(
    262                     "metric-collection-intervals", key, intervals.get(key).toString());
    263         }
    264 
    265         // Set up the classname.
    266         List<String> classnames = new ArrayList<>();
    267         classnames.add(TestJankinfoCollector.class.getName());
    268         for (String key : classnames) {
    269             setter.setOptionValue("metric-collector-command-classes", key);
    270         }
    271 
    272         DeviceMetricData runData = new DeviceMetricData(mContext);
    273 
    274         // Start the tests, which should fail with the expected error message.
    275         mMultipleMetricCollector.init(mContext, mMockListener);
    276 
    277         try {
    278             mMultipleMetricCollector.onTestRunStart(runData);
    279             fail("Should throw illegal argument exception in case of negative intervals.");
    280         } catch (IllegalArgumentException e) {
    281             assertEquals(expectedStderr, e.getMessage());
    282         }
    283     }
    284 }
    285