1 /*
2  * Copyright (C) 2018 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.collectors;
17 
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertTrue;
21 import static org.mockito.Mockito.doReturn;
22 import static org.mockito.Mockito.mock;
23 
24 import android.service.batterystats.BatteryStatsServiceDumpProto;
25 
26 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
27 import com.android.tradefed.config.OptionSetter;
28 import com.android.tradefed.device.metric.DeviceMetricData;
29 import com.android.tradefed.device.metric.FilePullerDeviceMetricCollector;
30 import com.android.tradefed.invoker.IInvocationContext;
31 import com.android.tradefed.metrics.proto.MetricMeasurement.Measurements;
32 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
33 import com.android.tradefed.result.CollectingTestListener;
34 import com.android.tradefed.result.TestRunResult;
35 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
36 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
37 
38 import org.junit.Before;
39 import org.junit.Test;
40 import org.junit.runner.RunWith;
41 
42 import java.io.BufferedInputStream;
43 import java.io.File;
44 import java.io.FileInputStream;
45 import java.io.IOException;
46 import java.io.InputStream;
47 import java.util.Arrays;
48 import java.util.Collection;
49 
50 /**
51  * Host side tests for the Batterystats collector, this ensure that we are able to use the
52  * collector in a similar way as the infra.
53  *
54  * Command:
55  * mm CollectorHostsideLibTest CollectorDeviceLibTest -j16
56  * tradefed.sh run commandAndExit template/local_min --template:map test=CollectorHostsideLibTest
57  */
58 @RunWith(DeviceJUnit4ClassRunner.class)
59 public class BatterystatsCollectorHostTest extends BaseHostJUnit4Test {
60     private static final String TEST_APK = "CollectorDeviceLibTest.apk";
61     private static final String PACKAGE_NAME = "android.device.collectors";
62     private static final String AJUR_RUNNER = "androidx.test.runner.AndroidJUnitRunner";
63 
64     private static final String BATTERYSTATS_COLLECTOR =
65             "android.device.collectors.BatteryStatsListener";
66     private static final String BATTERYSTATS_PROTO = "batterystatsproto";
67 
68     private RemoteAndroidTestRunner mTestRunner;
69     private IInvocationContext mContext;
70 
71     @Before
setUp()72     public void setUp() throws Exception {
73         installPackage(TEST_APK);
74         assertTrue(isPackageInstalled(PACKAGE_NAME));
75         mTestRunner =
76                 new RemoteAndroidTestRunner(PACKAGE_NAME, AJUR_RUNNER, getDevice().getIDevice());
77         mContext = mock(IInvocationContext.class);
78         doReturn(Arrays.asList(getDevice())).when(mContext).getDevices();
79         doReturn(Arrays.asList(getBuild())).when(mContext).getBuildInfos();
80     }
81 
82     /**
83      * Test that BatteryStatsListener collects batterystats and records to a file per run.
84      */
85     @Test
testBatteryStatsListener_perRun()86     public void testBatteryStatsListener_perRun() throws Exception {
87         mTestRunner.addInstrumentationArg("listener", BATTERYSTATS_COLLECTOR);
88         mTestRunner.addInstrumentationArg("batterystats-format", "file:batterystats-log");
89         mTestRunner.addInstrumentationArg("batterystats-per-run", "true");
90         mTestRunner.setClassName("android.device.collectors.BatteryStatsListenerTest");
91         CollectingTestListener listener = new CollectingTestListener();
92         FilePullerDeviceMetricCollector collector = new FilePullerDeviceMetricCollector() {
93             @Override
94             public void processMetricFile(String key, File metricFile, DeviceMetricData runData) {
95                 assertTrue(metricFile.getName().contains(BATTERYSTATS_PROTO));
96 
97                 runData.addMetric(key, Metric.newBuilder().setMeasurements(
98                         Measurements.newBuilder().setSingleString(metricFile.getAbsolutePath())
99                                 .build()));
100                 try (
101                         InputStream is = new BufferedInputStream(new FileInputStream(metricFile))
102                 ) {
103                     BatteryStatsServiceDumpProto bssdp = BatteryStatsServiceDumpProto.parseFrom(is);
104                     assertTrue(bssdp.hasBatterystats());
105                 } catch (IOException e) {
106                     throw new RuntimeException(e);
107                 } finally {
108                     assertTrue(metricFile.delete());
109                 }
110             }
111             @Override
112             public void processMetricDirectory(String key, File metricDirectory,
113                     DeviceMetricData runData) {
114             }
115         };
116         OptionSetter optionSetter = new OptionSetter(collector);
117         String pattern = String.format("%s_.*", BATTERYSTATS_COLLECTOR);
118         optionSetter.setOptionValue("pull-pattern-keys", pattern);
119         collector.init(mContext, listener);
120         assertTrue(getDevice().runInstrumentationTests(mTestRunner, collector));
121 
122         Collection<TestRunResult> results = listener.getRunResults();
123         assertEquals(1, results.size());
124         TestRunResult result = results.iterator().next();
125         assertFalse(result.isRunFailure());
126         assertFalse(result.hasFailedTests());
127 
128         assertEquals(1, result.getRunMetrics().size());
129         String metricFileKey = result.getRunMetrics().keySet().iterator().next();
130         assertTrue(metricFileKey.contains(BATTERYSTATS_COLLECTOR));
131     }
132 
133     /**
134      * Test that BatteryStatsListener collects batterystats and records to a file per test.
135      */
136     @Test
testBatteryStatsListener_perTest()137     public void testBatteryStatsListener_perTest() throws Exception {
138         mTestRunner.addInstrumentationArg("listener", BATTERYSTATS_COLLECTOR);
139         mTestRunner.addInstrumentationArg("batterystats-format", "file:batterystats-log");
140         mTestRunner.addInstrumentationArg("batterystats-per-run", "false");
141         mTestRunner.setClassName("android.device.collectors.BatteryStatsListenerTest");
142         CollectingTestListener listener = new CollectingTestListener();
143         FilePullerDeviceMetricCollector collector = new FilePullerDeviceMetricCollector() {
144             @Override
145             public void processMetricFile(String key, File metricFile, DeviceMetricData runData) {
146                 assertTrue(metricFile.getName().contains(BATTERYSTATS_PROTO));
147                 try (
148                         InputStream is = new BufferedInputStream(new FileInputStream(metricFile))
149                 ) {
150                     BatteryStatsServiceDumpProto bssdp = BatteryStatsServiceDumpProto.parseFrom(is);
151                     assertTrue(bssdp.hasBatterystats());
152                 } catch (IOException e) {
153                     throw new RuntimeException(e);
154                 } finally {
155                     assertTrue(metricFile.delete());
156                 }
157             }
158             @Override
159             public void processMetricDirectory(String key, File metricDirectory,
160                     DeviceMetricData runData) {
161             }
162         };
163         OptionSetter optionSetter = new OptionSetter(collector);
164         String pattern = String.format("%s_.*", BATTERYSTATS_COLLECTOR);
165         optionSetter.setOptionValue("pull-pattern-keys", pattern);
166         collector.init(mContext, listener);
167         assertTrue(getDevice().runInstrumentationTests(mTestRunner, collector));
168     }
169 }
170