1 /* 2 * Copyright (C) 2022 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 17 package com.android.server.tare; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertNotNull; 21 import static org.junit.Assert.assertNull; 22 import static org.mockito.Mockito.doReturn; 23 import static org.mockito.Mockito.mock; 24 25 import androidx.test.filters.SmallTest; 26 import androidx.test.runner.AndroidJUnit4; 27 28 import com.android.internal.app.IBatteryStats; 29 30 import org.junit.Test; 31 import org.junit.runner.RunWith; 32 33 import java.util.ArrayList; 34 import java.util.List; 35 36 /** Test that the Analyst processes transactions correctly. */ 37 @RunWith(AndroidJUnit4.class) 38 @SmallTest 39 public class AnalystTest { 40 41 @Test testInitialState()42 public void testInitialState() { 43 final Analyst analyst = new Analyst(); 44 assertEquals(0, analyst.getReports().size()); 45 } 46 47 @Test testBatteryLevelChange()48 public void testBatteryLevelChange() { 49 final Analyst analyst = new Analyst(); 50 51 Analyst.Report expected = new Analyst.Report(); 52 expected.currentBatteryLevel = 75; 53 analyst.noteBatteryLevelChange(75); 54 assertEquals(1, analyst.getReports().size()); 55 assertReportsEqual(expected, analyst.getReports().get(0)); 56 57 // Discharging 58 analyst.noteBatteryLevelChange(54); 59 expected.currentBatteryLevel = 54; 60 expected.cumulativeBatteryDischarge = 21; 61 assertEquals(1, analyst.getReports().size()); 62 assertReportsEqual(expected, analyst.getReports().get(0)); 63 analyst.noteBatteryLevelChange(50); 64 expected.currentBatteryLevel = 50; 65 expected.cumulativeBatteryDischarge = 25; 66 assertEquals(1, analyst.getReports().size()); 67 assertReportsEqual(expected, analyst.getReports().get(0)); 68 69 // Charging 70 analyst.noteBatteryLevelChange(51); 71 expected.currentBatteryLevel = 51; 72 assertEquals(1, analyst.getReports().size()); 73 assertReportsEqual(expected, analyst.getReports().get(0)); 74 analyst.noteBatteryLevelChange(55); 75 expected.currentBatteryLevel = 55; 76 assertEquals(1, analyst.getReports().size()); 77 assertReportsEqual(expected, analyst.getReports().get(0)); 78 79 // Reset 80 analyst.noteBatteryLevelChange(100); 81 assertEquals(2, analyst.getReports().size()); 82 assertReportsEqual(expected, analyst.getReports().get(0)); 83 expected.currentBatteryLevel = 100; 84 expected.cumulativeBatteryDischarge = 0; 85 assertReportsEqual(expected, analyst.getReports().get(1)); 86 } 87 88 @Test testTransaction()89 public void testTransaction() { 90 runTestTransactions(new Analyst(), new Analyst.Report(), 1); 91 } 92 93 @Test testTransaction_PeriodChange()94 public void testTransaction_PeriodChange() throws Exception { 95 IBatteryStats iBatteryStats = mock(IBatteryStats.class); 96 final Analyst analyst = new Analyst(iBatteryStats); 97 98 // Reset from enough discharge. 99 Analyst.Report expected = new Analyst.Report(); 100 expected.currentBatteryLevel = 75; 101 analyst.noteBatteryLevelChange(75); 102 103 runTestTransactions(analyst, expected, 1); 104 105 expected.currentBatteryLevel = 49; 106 expected.cumulativeBatteryDischarge = 26; 107 analyst.noteBatteryLevelChange(49); 108 109 runTestTransactions(analyst, expected, 1); 110 111 expected = new Analyst.Report(); 112 expected.currentBatteryLevel = 90; 113 analyst.noteBatteryLevelChange(90); 114 expected.cumulativeBatteryDischarge = 0; 115 116 runTestTransactions(analyst, expected, 2); 117 118 // Reset from report being long enough. 119 doReturn(Analyst.MIN_REPORT_DURATION_FOR_RESET) 120 .when(iBatteryStats).computeBatteryScreenOffRealtimeMs(); 121 expected.currentBatteryLevel = 85; 122 analyst.noteBatteryLevelChange(85); 123 expected.cumulativeBatteryDischarge = 5; 124 expected.screenOffDurationMs = Analyst.MIN_REPORT_DURATION_FOR_RESET; 125 126 runTestTransactions(analyst, expected, 2); 127 128 expected.currentBatteryLevel = 79; 129 analyst.noteBatteryLevelChange(79); 130 expected.cumulativeBatteryDischarge = 11; 131 132 runTestTransactions(analyst, expected, 2); 133 134 expected = new Analyst.Report(); 135 expected.currentBatteryLevel = 80; 136 analyst.noteBatteryLevelChange(80); 137 expected.cumulativeBatteryDischarge = 0; 138 expected.screenOffDurationMs = 0; 139 140 runTestTransactions(analyst, expected, 3); 141 } 142 runTestTransactions(Analyst analyst, Analyst.Report lastExpectedReport, int numExpectedReports)143 private void runTestTransactions(Analyst analyst, Analyst.Report lastExpectedReport, 144 int numExpectedReports) { 145 Analyst.Report expected = lastExpectedReport; 146 147 // Profit 148 analyst.noteTransaction( 149 new Ledger.Transaction(0, 1000, EconomicPolicy.TYPE_ACTION, null, -51, 1)); 150 expected.cumulativeProfit += 50; 151 expected.numProfitableActions += 1; 152 assertEquals(numExpectedReports, analyst.getReports().size()); 153 assertReportsEqual(expected, analyst.getReports().get(numExpectedReports - 1)); 154 155 // Loss 156 analyst.noteTransaction( 157 new Ledger.Transaction(0, 1000, EconomicPolicy.TYPE_ACTION, null, -51, 100)); 158 expected.cumulativeLoss += 49; 159 expected.numUnprofitableActions += 1; 160 assertEquals(numExpectedReports, analyst.getReports().size()); 161 assertReportsEqual(expected, analyst.getReports().get(numExpectedReports - 1)); 162 163 // Reward 164 analyst.noteTransaction( 165 new Ledger.Transaction(0, 1000, EconomicPolicy.TYPE_REWARD, null, 51, 0)); 166 expected.cumulativeRewards += 51; 167 expected.numRewards += 1; 168 assertEquals(numExpectedReports, analyst.getReports().size()); 169 assertReportsEqual(expected, analyst.getReports().get(numExpectedReports - 1)); 170 171 // Regulations 172 analyst.noteTransaction( 173 new Ledger.Transaction(0, 1000, EconomicPolicy.TYPE_REGULATION, null, 25, 0)); 174 expected.cumulativePositiveRegulations += 25; 175 expected.numPositiveRegulations += 1; 176 assertEquals(numExpectedReports, analyst.getReports().size()); 177 assertReportsEqual(expected, analyst.getReports().get(numExpectedReports - 1)); 178 analyst.noteTransaction( 179 new Ledger.Transaction(0, 1000, EconomicPolicy.TYPE_REGULATION, null, -25, 0)); 180 expected.cumulativeNegativeRegulations += 25; 181 expected.numNegativeRegulations += 1; 182 assertEquals(numExpectedReports, analyst.getReports().size()); 183 assertReportsEqual(expected, analyst.getReports().get(numExpectedReports - 1)); 184 185 // No-ops 186 analyst.noteTransaction( 187 new Ledger.Transaction(0, 1000, EconomicPolicy.TYPE_ACTION, null, -100, 100)); 188 analyst.noteTransaction( 189 new Ledger.Transaction(0, 1000, EconomicPolicy.TYPE_REGULATION, null, 0, 0)); 190 analyst.noteTransaction( 191 new Ledger.Transaction(0, 1000, EconomicPolicy.TYPE_REWARD, null, 0, 0)); 192 assertEquals(numExpectedReports, analyst.getReports().size()); 193 } 194 195 @Test testLoadReports()196 public void testLoadReports() { 197 final Analyst analyst = new Analyst(); 198 199 List<Analyst.Report> expected = new ArrayList<>(); 200 analyst.loadReports(expected); 201 assertReportListsEqual(expected, analyst.getReports()); 202 203 Analyst.Report report1 = new Analyst.Report(); 204 report1.cumulativeBatteryDischarge = 1; 205 report1.currentBatteryLevel = 2; 206 report1.cumulativeProfit = 3; 207 report1.numProfitableActions = 4; 208 report1.cumulativeLoss = 5; 209 report1.numUnprofitableActions = 6; 210 report1.cumulativeRewards = 7; 211 report1.numRewards = 8; 212 report1.cumulativePositiveRegulations = 9; 213 report1.numPositiveRegulations = 10; 214 report1.cumulativeNegativeRegulations = 11; 215 report1.numNegativeRegulations = 12; 216 expected.add(report1); 217 analyst.loadReports(expected); 218 assertReportListsEqual(expected, analyst.getReports()); 219 220 Analyst.Report report2 = new Analyst.Report(); 221 report2.cumulativeBatteryDischarge = 10; 222 report2.currentBatteryLevel = 20; 223 report2.cumulativeProfit = 30; 224 report2.numProfitableActions = 40; 225 report2.cumulativeLoss = 50; 226 report2.numUnprofitableActions = 60; 227 report2.cumulativeRewards = 70; 228 report2.numRewards = 80; 229 report2.cumulativePositiveRegulations = 90; 230 report2.numPositiveRegulations = 100; 231 report2.cumulativeNegativeRegulations = 110; 232 report2.numNegativeRegulations = 120; 233 expected.add(report2); 234 analyst.loadReports(expected); 235 assertReportListsEqual(expected, analyst.getReports()); 236 } 237 assertReportsEqual(Analyst.Report expected, Analyst.Report actual)238 private void assertReportsEqual(Analyst.Report expected, Analyst.Report actual) { 239 if (expected == null) { 240 assertNull(actual); 241 return; 242 } 243 assertNotNull(actual); 244 assertEquals(expected.cumulativeBatteryDischarge, actual.cumulativeBatteryDischarge); 245 assertEquals(expected.currentBatteryLevel, actual.currentBatteryLevel); 246 assertEquals(expected.cumulativeProfit, actual.cumulativeProfit); 247 assertEquals(expected.numProfitableActions, actual.numProfitableActions); 248 assertEquals(expected.cumulativeLoss, actual.cumulativeLoss); 249 assertEquals(expected.numUnprofitableActions, actual.numUnprofitableActions); 250 assertEquals(expected.cumulativeRewards, actual.cumulativeRewards); 251 assertEquals(expected.numRewards, actual.numRewards); 252 assertEquals(expected.cumulativePositiveRegulations, actual.cumulativePositiveRegulations); 253 assertEquals(expected.numPositiveRegulations, actual.numPositiveRegulations); 254 assertEquals(expected.cumulativeNegativeRegulations, actual.cumulativeNegativeRegulations); 255 assertEquals(expected.numNegativeRegulations, actual.numNegativeRegulations); 256 assertEquals(expected.screenOffDurationMs, actual.screenOffDurationMs); 257 assertEquals(expected.screenOffDischargeMah, actual.screenOffDischargeMah); 258 } 259 assertReportListsEqual(List<Analyst.Report> expected, List<Analyst.Report> actual)260 private void assertReportListsEqual(List<Analyst.Report> expected, 261 List<Analyst.Report> actual) { 262 if (expected == null) { 263 assertNull(actual); 264 return; 265 } 266 assertNotNull(actual); 267 assertEquals(expected.size(), actual.size()); 268 for (int i = 0; i < expected.size(); ++i) { 269 assertReportsEqual(expected.get(i), actual.get(i)); 270 } 271 } 272 } 273