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 17 package com.android.car.storagemonitoring; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertTrue; 23 import static org.junit.Assert.fail; 24 import static org.mockito.ArgumentMatchers.any; 25 import static org.mockito.ArgumentMatchers.anyString; 26 import static org.mockito.Mockito.doAnswer; 27 import static org.mockito.Mockito.doReturn; 28 29 import android.car.storagemonitoring.IoStats; 30 import android.car.storagemonitoring.IoStatsEntry; 31 import android.car.storagemonitoring.LifetimeWriteInfo; 32 import android.car.storagemonitoring.UidIoRecord; 33 import android.car.storagemonitoring.WearEstimate; 34 import android.car.storagemonitoring.WearEstimateChange; 35 import android.hardware.health.V2_0.IHealth; 36 import android.hardware.health.V2_0.IHealth.getStorageInfoCallback; 37 import android.hardware.health.V2_0.Result; 38 import android.hardware.health.V2_0.StorageInfo; 39 import android.os.Parcel; 40 import android.test.suitebuilder.annotation.MediumTest; 41 import android.util.JsonReader; 42 import android.util.JsonWriter; 43 import android.util.SparseArray; 44 45 import com.android.car.test.utils.TemporaryDirectory; 46 import com.android.car.test.utils.TemporaryFile; 47 48 import org.json.JSONObject; 49 import org.junit.Test; 50 import org.junit.runner.RunWith; 51 import org.mockito.Mock; 52 import org.mockito.junit.MockitoJUnitRunner; 53 54 import java.io.FileWriter; 55 import java.io.StringReader; 56 import java.io.StringWriter; 57 import java.nio.file.Files; 58 import java.time.Instant; 59 import java.util.ArrayList; 60 import java.util.Arrays; 61 import java.util.Collections; 62 import java.util.List; 63 64 /** 65 * Tests the storage monitoring API in CarService. 66 */ 67 @RunWith(MockitoJUnitRunner.class) 68 @MediumTest 69 public class CarStorageMonitoringTest { 70 static final String TAG = CarStorageMonitoringTest.class.getSimpleName(); 71 72 @Mock private IHealth mMockedHal; 73 @Mock private HealthServiceWearInfoProvider.IHealthSupplier mHealthServiceSupplier; 74 75 @Test testEMmcWearInformationProvider()76 public void testEMmcWearInformationProvider() throws Exception { 77 try (TemporaryFile lifetimeFile = new TemporaryFile(TAG)) { 78 try (TemporaryFile eolFile = new TemporaryFile(TAG)) { 79 lifetimeFile.write("0x05 0x00"); 80 eolFile.write("01"); 81 82 EMmcWearInformationProvider wearInfoProvider = new EMmcWearInformationProvider( 83 lifetimeFile.getFile(), eolFile.getFile()); 84 85 WearInformation wearInformation = wearInfoProvider.load(); 86 87 assertThat(wearInformation).isNotNull(); 88 assertThat(wearInformation.lifetimeEstimateA).isEqualTo(40); 89 assertThat(wearInformation.lifetimeEstimateB) 90 .isEqualTo(WearInformation.UNKNOWN_LIFETIME_ESTIMATE); 91 assertThat(wearInformation.preEolInfo) 92 .isEqualTo(WearInformation.PRE_EOL_INFO_NORMAL); 93 } 94 } 95 } 96 97 @Test testUfsWearInformationProvider()98 public void testUfsWearInformationProvider() throws Exception { 99 try (TemporaryFile lifetimeFile = new TemporaryFile(TAG)) { 100 lifetimeFile.write("ufs version: 1.0\n" + 101 "Health Descriptor[Byte offset 0x2]: bPreEOLInfo = 0x2\n" + 102 "Health Descriptor[Byte offset 0x1]: bDescriptionIDN = 0x1\n" + 103 "Health Descriptor[Byte offset 0x3]: bDeviceLifeTimeEstA = 0x0\n" + 104 "Health Descriptor[Byte offset 0x5]: VendorPropInfo = somedatahere\n" + 105 "Health Descriptor[Byte offset 0x4]: bDeviceLifeTimeEstB = 0xA\n"); 106 107 UfsWearInformationProvider wearInfoProvider = new UfsWearInformationProvider( 108 lifetimeFile.getFile()); 109 110 WearInformation wearInformation = wearInfoProvider.load(); 111 112 assertThat(wearInformation).isNotNull(); 113 assertThat(wearInformation.lifetimeEstimateB).isEqualTo(90); 114 assertThat(wearInformation.preEolInfo).isEqualTo(WearInformation.PRE_EOL_INFO_WARNING); 115 assertThat(wearInformation.lifetimeEstimateA) 116 .isEqualTo(WearInformation.UNKNOWN_LIFETIME_ESTIMATE); 117 } 118 } 119 120 @Test testHealthServiceWearInformationProvider()121 public void testHealthServiceWearInformationProvider() throws Exception { 122 StorageInfo storageInfo = new StorageInfo(); 123 storageInfo.eol = WearInformation.PRE_EOL_INFO_NORMAL; 124 storageInfo.lifetimeA = 3; 125 storageInfo.lifetimeB = WearInformation.UNKNOWN_LIFETIME_ESTIMATE; 126 storageInfo.attr.isInternal = true; 127 HealthServiceWearInfoProvider wearInfoProvider = new HealthServiceWearInfoProvider(); 128 wearInfoProvider.setHealthSupplier(mHealthServiceSupplier); 129 130 doReturn(mMockedHal) 131 .when(mHealthServiceSupplier).get(anyString()); 132 doAnswer((invocation) -> { 133 ArrayList<StorageInfo> list = new ArrayList<StorageInfo>(); 134 list.add(storageInfo); 135 ((IHealth.getStorageInfoCallback) invocation.getArguments()[0]) 136 .onValues(Result.SUCCESS, list); 137 return null; 138 }).when(mMockedHal).getStorageInfo(any(getStorageInfoCallback.class)); 139 WearInformation wearInformation = wearInfoProvider.load(); 140 141 assertThat(wearInformation).isNotNull(); 142 assertThat(wearInformation.lifetimeEstimateA).isEqualTo(20); 143 assertThat(wearInformation.lifetimeEstimateB).isEqualTo(storageInfo.lifetimeB); 144 assertThat(wearInformation.preEolInfo).isEqualTo(storageInfo.eol); 145 } 146 147 @Test 148 @SuppressWarnings("TruthSelfEquals") 149 // TODO: use EqualsTester to check equality with itself, 150 // Remove @SuppressWarnings("TruthSelfEquals") at other places too testWearEstimateEquality()151 public void testWearEstimateEquality() { 152 WearEstimate wearEstimate1 = new WearEstimate(10, 20); 153 WearEstimate wearEstimate2 = new WearEstimate(10, 20); 154 WearEstimate wearEstimate3 = new WearEstimate(20, 30); 155 assertThat(wearEstimate1).isEqualTo(wearEstimate1); 156 assertThat(wearEstimate2).isEqualTo(wearEstimate1); 157 assertThat(wearEstimate1).isNotSameInstanceAs(wearEstimate3); 158 } 159 160 @Test testWearEstimateParcel()161 public void testWearEstimateParcel() throws Exception { 162 WearEstimate originalWearEstimate = new WearEstimate(10, 20); 163 Parcel p = Parcel.obtain(); 164 originalWearEstimate.writeToParcel(p, 0); 165 p.setDataPosition(0); 166 WearEstimate newWearEstimate = new WearEstimate(p); 167 assertThat(newWearEstimate).isEqualTo(originalWearEstimate); 168 p.recycle(); 169 } 170 171 @Test 172 @SuppressWarnings("TruthSelfEquals") testWearEstimateChangeEquality()173 public void testWearEstimateChangeEquality() { 174 WearEstimateChange wearEstimateChange1 = new WearEstimateChange( 175 new WearEstimate(10, 20), 176 new WearEstimate(20, 30), 177 5000L, 178 Instant.now(), 179 false); 180 WearEstimateChange wearEstimateChange2 = new WearEstimateChange( 181 new WearEstimate(10, 20), 182 new WearEstimate(20, 30), 183 5000L, 184 wearEstimateChange1.dateAtChange, 185 false); 186 assertThat(wearEstimateChange1).isEqualTo(wearEstimateChange1); 187 assertThat(wearEstimateChange2).isEqualTo(wearEstimateChange1); 188 WearEstimateChange wearEstimateChange3 = new WearEstimateChange( 189 new WearEstimate(10, 30), 190 new WearEstimate(20, 30), 191 3000L, 192 Instant.now(), 193 true); 194 assertThat(wearEstimateChange1).isNotSameInstanceAs(wearEstimateChange3); 195 } 196 197 @Test testWearEstimateChangeParcel()198 public void testWearEstimateChangeParcel() throws Exception { 199 WearEstimateChange originalWearEstimateChange = new WearEstimateChange( 200 new WearEstimate(10, 0), 201 new WearEstimate(20, 10), 202 123456789L, 203 Instant.now(), 204 false); 205 Parcel p = Parcel.obtain(); 206 originalWearEstimateChange.writeToParcel(p, 0); 207 p.setDataPosition(0); 208 WearEstimateChange newWearEstimateChange = new WearEstimateChange(p); 209 assertThat(newWearEstimateChange).isEqualTo(originalWearEstimateChange); 210 p.recycle(); 211 } 212 213 @Test testWearEstimateJson()214 public void testWearEstimateJson() throws Exception { 215 WearEstimate originalWearEstimate = new WearEstimate(20, 0); 216 StringWriter stringWriter = new StringWriter(1024); 217 JsonWriter jsonWriter = new JsonWriter(stringWriter); 218 originalWearEstimate.writeToJson(jsonWriter); 219 StringReader stringReader = new StringReader(stringWriter.toString()); 220 JsonReader jsonReader = new JsonReader(stringReader); 221 WearEstimate newWearEstimate = new WearEstimate(jsonReader); 222 assertThat(newWearEstimate).isEqualTo(originalWearEstimate); 223 } 224 225 @Test testWearEstimateRecordJson()226 public void testWearEstimateRecordJson() throws Exception { 227 try (TemporaryFile temporaryFile = new TemporaryFile(TAG)) { 228 WearEstimateRecord originalWearEstimateRecord = new WearEstimateRecord(new WearEstimate(10, 20), 229 new WearEstimate(10, 30), 5000, Instant.ofEpochMilli(1000)); 230 try (JsonWriter jsonWriter = new JsonWriter(new FileWriter(temporaryFile.getFile()))) { 231 originalWearEstimateRecord.writeToJson(jsonWriter); 232 } 233 JSONObject jsonObject = new JSONObject( 234 new String(Files.readAllBytes(temporaryFile.getPath()))); 235 WearEstimateRecord newWearEstimateRecord = new WearEstimateRecord(jsonObject); 236 assertThat(newWearEstimateRecord).isEqualTo(originalWearEstimateRecord); 237 } 238 } 239 240 @Test 241 @SuppressWarnings("TruthSelfEquals") testWearEstimateRecordEquality()242 public void testWearEstimateRecordEquality() throws Exception { 243 WearEstimateRecord wearEstimateRecord1 = new WearEstimateRecord(WearEstimate.UNKNOWN_ESTIMATE, 244 new WearEstimate(10, 20), 5000, Instant.ofEpochMilli(2000)); 245 WearEstimateRecord wearEstimateRecord2 = new WearEstimateRecord(WearEstimate.UNKNOWN_ESTIMATE, 246 new WearEstimate(10, 20), 5000, Instant.ofEpochMilli(2000)); 247 WearEstimateRecord wearEstimateRecord3 = new WearEstimateRecord(WearEstimate.UNKNOWN_ESTIMATE, 248 new WearEstimate(10, 40), 5000, Instant.ofEpochMilli(1000)); 249 250 assertThat(wearEstimateRecord1).isEqualTo(wearEstimateRecord1); 251 assertThat(wearEstimateRecord2).isEqualTo(wearEstimateRecord1); 252 assertThat(wearEstimateRecord1).isNotSameInstanceAs(wearEstimateRecord3); 253 } 254 255 @Test testWearHistoryJson()256 public void testWearHistoryJson() throws Exception { 257 try (TemporaryFile temporaryFile = new TemporaryFile(TAG)) { 258 WearEstimateRecord wearEstimateRecord1 = new WearEstimateRecord( 259 WearEstimate.UNKNOWN_ESTIMATE, 260 new WearEstimate(10, 20), 5000, Instant.ofEpochMilli(2000)); 261 WearEstimateRecord wearEstimateRecord2 = new WearEstimateRecord( 262 wearEstimateRecord1.getOldWearEstimate(), 263 new WearEstimate(10, 40), 9000, Instant.ofEpochMilli(16000)); 264 WearEstimateRecord wearEstimateRecord3 = new WearEstimateRecord( 265 wearEstimateRecord2.getOldWearEstimate(), 266 new WearEstimate(20, 40), 12000, Instant.ofEpochMilli(21000)); 267 WearHistory originalWearHistory = WearHistory.fromRecords(wearEstimateRecord1, 268 wearEstimateRecord2, wearEstimateRecord3); 269 try (JsonWriter jsonWriter = new JsonWriter(new FileWriter(temporaryFile.getFile()))) { 270 originalWearHistory.writeToJson(jsonWriter); 271 } 272 JSONObject jsonObject = new JSONObject( 273 new String(Files.readAllBytes(temporaryFile.getPath()))); 274 WearHistory newWearHistory = new WearHistory(jsonObject); 275 assertThat(newWearHistory).isEqualTo(originalWearHistory); 276 } 277 } 278 279 @Test 280 @SuppressWarnings("TruthSelfEquals") testWearHistoryEquality()281 public void testWearHistoryEquality() throws Exception { 282 WearEstimateRecord wearEstimateRecord1 = new WearEstimateRecord( 283 WearEstimate.UNKNOWN_ESTIMATE, 284 new WearEstimate(10, 20), 5000, Instant.ofEpochMilli(2000)); 285 WearEstimateRecord wearEstimateRecord2 = new WearEstimateRecord( 286 wearEstimateRecord1.getOldWearEstimate(), 287 new WearEstimate(10, 40), 9000, Instant.ofEpochMilli(16000)); 288 WearEstimateRecord wearEstimateRecord3 = new WearEstimateRecord( 289 wearEstimateRecord2.getOldWearEstimate(), 290 new WearEstimate(20, 40), 12000, Instant.ofEpochMilli(21000)); 291 WearEstimateRecord wearEstimateRecord4 = new WearEstimateRecord( 292 wearEstimateRecord3.getOldWearEstimate(), 293 new WearEstimate(30, 50), 17000, Instant.ofEpochMilli(34000)); 294 WearEstimateRecord wearEstimateRecord5 = new WearEstimateRecord( 295 wearEstimateRecord3.getOldWearEstimate(), 296 new WearEstimate(20, 50), 15000, Instant.ofEpochMilli(34000)); 297 298 WearHistory wearHistory1 = WearHistory.fromRecords(wearEstimateRecord1, 299 wearEstimateRecord2, wearEstimateRecord3, wearEstimateRecord4); 300 WearHistory wearHistory2 = WearHistory.fromRecords(wearEstimateRecord4, 301 wearEstimateRecord1, wearEstimateRecord2, wearEstimateRecord3); 302 WearHistory wearHistory3 = WearHistory.fromRecords(wearEstimateRecord1, 303 wearEstimateRecord2, wearEstimateRecord3, wearEstimateRecord5); 304 305 assertThat(wearHistory1).isEqualTo(wearHistory1); 306 assertThat(wearHistory2).isEqualTo(wearHistory1); 307 assertThat(wearHistory1).isNotSameInstanceAs(wearHistory3); 308 } 309 310 @Test testWearHistoryToChanges()311 public void testWearHistoryToChanges() { 312 WearEstimateRecord wearEstimateRecord1 = new WearEstimateRecord( 313 WearEstimate.UNKNOWN_ESTIMATE, 314 new WearEstimate(10, 20), 3600000, Instant.ofEpochMilli(2000)); 315 WearEstimateRecord wearEstimateRecord2 = new WearEstimateRecord( 316 wearEstimateRecord1.getOldWearEstimate(), 317 new WearEstimate(10, 40), 172000000, Instant.ofEpochMilli(16000)); 318 WearEstimateRecord wearEstimateRecord3 = new WearEstimateRecord( 319 wearEstimateRecord2.getOldWearEstimate(), 320 new WearEstimate(20, 40), 172000001, Instant.ofEpochMilli(21000)); 321 322 WearHistory wearHistory = WearHistory.fromRecords(wearEstimateRecord1, 323 wearEstimateRecord2, wearEstimateRecord3); 324 325 List<WearEstimateChange> wearEstimateChanges = wearHistory.toWearEstimateChanges(1); 326 327 assertThat(wearEstimateChanges.size()).isEqualTo(3); 328 WearEstimateChange unknownToOne = wearEstimateChanges.get(0); 329 WearEstimateChange oneToTwo = wearEstimateChanges.get(1); 330 WearEstimateChange twoToThree = wearEstimateChanges.get(2); 331 332 assertThat(wearEstimateRecord1.getOldWearEstimate()).isEqualTo(unknownToOne.oldEstimate); 333 assertThat(wearEstimateRecord1.getNewWearEstimate()).isEqualTo(unknownToOne.newEstimate); 334 assertThat(wearEstimateRecord1.getTotalCarServiceUptime()) 335 .isEqualTo(unknownToOne.uptimeAtChange); 336 assertThat(wearEstimateRecord1.getUnixTimestamp()).isEqualTo(unknownToOne.dateAtChange); 337 assertThat(unknownToOne.isAcceptableDegradation).isTrue(); 338 339 assertThat(wearEstimateRecord2.getOldWearEstimate()).isEqualTo(oneToTwo.oldEstimate); 340 assertThat(wearEstimateRecord2.getNewWearEstimate()).isEqualTo(oneToTwo.newEstimate); 341 assertThat(wearEstimateRecord2.getTotalCarServiceUptime()) 342 .isEqualTo(oneToTwo.uptimeAtChange); 343 assertThat(wearEstimateRecord2.getUnixTimestamp()).isEqualTo(oneToTwo.dateAtChange); 344 assertThat(oneToTwo.isAcceptableDegradation).isTrue(); 345 346 assertThat(wearEstimateRecord3.getOldWearEstimate()).isEqualTo(twoToThree.oldEstimate); 347 assertThat(wearEstimateRecord3.getNewWearEstimate()).isEqualTo(twoToThree.newEstimate); 348 assertThat(wearEstimateRecord3.getTotalCarServiceUptime()) 349 .isEqualTo(twoToThree.uptimeAtChange); 350 assertThat(wearEstimateRecord3.getUnixTimestamp()).isEqualTo(twoToThree.dateAtChange); 351 assertThat(twoToThree.isAcceptableDegradation).isFalse(); 352 } 353 354 @Test testUidIoStatEntry()355 public void testUidIoStatEntry() throws Exception { 356 try (TemporaryFile statsFile = new TemporaryFile(TAG)) { 357 statsFile.write("0 256797495 181736102 362132480 947167232 0 0 0 0 250 0\n" 358 + "1006 489007 196802 0 20480 51474 2048 1024 2048 1 1\n"); 359 360 ProcfsUidIoStatsProvider statsProvider = new ProcfsUidIoStatsProvider( 361 statsFile.getPath()); 362 363 SparseArray<UidIoRecord> entries = statsProvider.load(); 364 365 assertThat(entries).isNotNull(); 366 assertThat(entries.size()).isEqualTo(2); 367 368 IoStatsEntry entry = new IoStatsEntry(entries.get(0), 1234); 369 assertThat(entry).isNotNull(); 370 assertThat(entry.uid).isEqualTo(0); 371 assertThat(entry.runtimeMillis).isEqualTo(1234); 372 assertThat(entry.foreground.bytesRead).isEqualTo(256797495); 373 assertThat(entry.foreground.bytesWritten).isEqualTo(181736102); 374 assertThat(entry.foreground.bytesReadFromStorage).isEqualTo(362132480); 375 assertThat(entry.foreground.bytesWrittenToStorage).isEqualTo(947167232); 376 assertThat(entry.foreground.fsyncCalls).isEqualTo(250); 377 assertThat(entry.background.bytesRead).isEqualTo(0); 378 assertThat(entry.background.bytesWritten).isEqualTo(0); 379 assertThat(entry.background.bytesReadFromStorage).isEqualTo(0); 380 assertThat(entry.background.bytesWrittenToStorage).isEqualTo(0); 381 assertThat(entry.background.fsyncCalls).isEqualTo(0); 382 383 entry = new IoStatsEntry(entries.get(1006), 4321); 384 assertThat(entry).isNotNull(); 385 assertThat(entry.uid).isEqualTo(1006); 386 assertThat(entry.runtimeMillis).isEqualTo(4321); 387 assertThat(entry.foreground.bytesRead).isEqualTo(489007); 388 assertThat(entry.foreground.bytesWritten).isEqualTo(196802); 389 assertThat(entry.foreground.bytesReadFromStorage).isEqualTo(0); 390 assertThat(entry.foreground.bytesWrittenToStorage).isEqualTo(20480); 391 assertThat(entry.foreground.fsyncCalls).isEqualTo(1); 392 assertThat(entry.background.bytesRead).isEqualTo(51474); 393 assertThat(entry.background.bytesWritten).isEqualTo(2048); 394 assertThat(entry.background.bytesReadFromStorage).isEqualTo(1024); 395 assertThat(entry.background.bytesWrittenToStorage).isEqualTo(2048); 396 assertThat(entry.background.fsyncCalls).isEqualTo(1); 397 } 398 } 399 400 @Test testUidIoStatEntryMissingFields()401 public void testUidIoStatEntryMissingFields() throws Exception { 402 try (TemporaryFile statsFile = new TemporaryFile(TAG)) { 403 statsFile.write("0 256797495 181736102 362132480 947167232 0 0 0 0 250 0\n" 404 + "1 2 3 4 5 6 7 8 9\n"); 405 406 ProcfsUidIoStatsProvider statsProvider = new ProcfsUidIoStatsProvider( 407 statsFile.getPath()); 408 409 SparseArray<UidIoRecord> entries = statsProvider.load(); 410 411 assertThat(entries).isNull(); 412 } 413 } 414 415 @Test testUidIoStatEntryNonNumericFields()416 public void testUidIoStatEntryNonNumericFields() throws Exception { 417 try (TemporaryFile statsFile = new TemporaryFile(TAG)) { 418 statsFile.write("0 256797495 181736102 362132480 947167232 0 0 0 0 250 0\n" 419 + "notanumber 489007 196802 0 20480 51474 2048 1024 2048 1 1\n"); 420 421 ProcfsUidIoStatsProvider statsProvider = new ProcfsUidIoStatsProvider( 422 statsFile.getPath()); 423 424 SparseArray<UidIoRecord> entries = statsProvider.load(); 425 426 assertThat(entries).isNull(); 427 } 428 } 429 430 @Test 431 @SuppressWarnings("TruthSelfEquals") testUidIoStatEntryEquality()432 public void testUidIoStatEntryEquality() throws Exception { 433 IoStatsEntry statEntry1 = new IoStatsEntry(10, 1234, 434 new IoStatsEntry.Metrics(10, 20, 30, 40, 50), 435 new IoStatsEntry.Metrics(100, 200, 300, 400, 500)); 436 IoStatsEntry statEntry2 = new IoStatsEntry(10, 1234, 437 new IoStatsEntry.Metrics(10, 20, 30, 40, 50), 438 new IoStatsEntry.Metrics(100, 200, 300, 400, 500)); 439 IoStatsEntry statEntry3 = new IoStatsEntry(30, 4567, 440 new IoStatsEntry.Metrics(1, 20, 30, 42, 50), 441 new IoStatsEntry.Metrics(10, 200, 300, 420, 500)); 442 IoStatsEntry statEntry4 = new IoStatsEntry(11, 6541, 443 new IoStatsEntry.Metrics(10, 20, 30, 40, 50), 444 new IoStatsEntry.Metrics(100, 200, 300, 400, 500)); 445 IoStatsEntry statEntry5 = new IoStatsEntry(10, 1234, 446 new IoStatsEntry.Metrics(10, 20, 30, 40, 0), 447 new IoStatsEntry.Metrics(100, 200, 300, 400, 500)); 448 449 assertThat(statEntry1).isEqualTo(statEntry1); 450 assertThat(statEntry2).isEqualTo(statEntry1); 451 assertThat(statEntry1).isNotSameInstanceAs(statEntry3); 452 assertThat(statEntry1).isNotSameInstanceAs(statEntry4); 453 assertThat(statEntry1).isNotSameInstanceAs(statEntry5); 454 } 455 456 @Test testUidIoStatEntryParcel()457 public void testUidIoStatEntryParcel() throws Exception { 458 IoStatsEntry statEntry = new IoStatsEntry(10, 5000, 459 new IoStatsEntry.Metrics(10, 20, 30, 40, 50), 460 new IoStatsEntry.Metrics(100, 200, 300, 400, 500)); 461 Parcel p = Parcel.obtain(); 462 statEntry.writeToParcel(p, 0); 463 p.setDataPosition(0); 464 IoStatsEntry other = new IoStatsEntry(p); 465 assertThat(statEntry).isEqualTo(other); 466 } 467 468 @Test testUidIoStatEntryJson()469 public void testUidIoStatEntryJson() throws Exception { 470 try (TemporaryFile temporaryFile = new TemporaryFile(TAG)) { 471 IoStatsEntry statEntry = new IoStatsEntry(10, 1200, 472 new IoStatsEntry.Metrics(10, 20, 30, 40, 50), 473 new IoStatsEntry.Metrics(100, 200, 300, 400, 500)); 474 try (JsonWriter jsonWriter = new JsonWriter(new FileWriter(temporaryFile.getFile()))) { 475 statEntry.writeToJson(jsonWriter); 476 } 477 JSONObject jsonObject = new JSONObject( 478 new String(Files.readAllBytes(temporaryFile.getPath()))); 479 IoStatsEntry other = new IoStatsEntry(jsonObject); 480 assertThat(other).isEqualTo(statEntry); 481 } 482 } 483 484 485 @Test testUidIoStatEntryDelta()486 public void testUidIoStatEntryDelta() throws Exception { 487 IoStatsEntry statEntry1 = new IoStatsEntry(10, 1000, 488 new IoStatsEntry.Metrics(10, 20, 30, 40, 50), 489 new IoStatsEntry.Metrics(60, 70, 80, 90, 100)); 490 491 IoStatsEntry statEntry2 = new IoStatsEntry(10,2000, 492 new IoStatsEntry.Metrics(110, 120, 130, 140, 150), 493 new IoStatsEntry.Metrics(260, 370, 480, 500, 110)); 494 495 IoStatsEntry statEntry3 = new IoStatsEntry(30, 3000, 496 new IoStatsEntry.Metrics(10, 20, 30, 40, 50), 497 new IoStatsEntry.Metrics(100, 200, 300, 400, 500)); 498 499 500 IoStatsEntry delta21 = statEntry2.delta(statEntry1); 501 assertThat(delta21).isNotNull(); 502 assertThat(delta21.uid).isEqualTo(statEntry1.uid); 503 504 assertThat(delta21.runtimeMillis).isEqualTo(1000); 505 assertThat(delta21.foreground.bytesRead).isEqualTo(100); 506 assertThat(delta21.foreground.bytesWritten).isEqualTo(100); 507 assertThat(delta21.foreground.bytesReadFromStorage).isEqualTo(100); 508 assertThat(delta21.foreground.bytesWrittenToStorage).isEqualTo(100); 509 assertThat(delta21.foreground.fsyncCalls).isEqualTo(100); 510 511 assertThat(delta21.background.bytesRead).isEqualTo(200); 512 assertThat(delta21.background.bytesWritten).isEqualTo(300); 513 assertThat(delta21.background.bytesReadFromStorage).isEqualTo(400); 514 assertThat(delta21.background.bytesWrittenToStorage).isEqualTo(410); 515 assertThat(delta21.background.fsyncCalls).isEqualTo(10); 516 517 try { 518 IoStatsEntry delta31 = statEntry3.delta(statEntry1); 519 fail("delta only allowed on stats for matching user ID"); 520 } catch (IllegalArgumentException e) { 521 // test passed 522 } 523 } 524 525 @Test testUidIoStatsRecordDelta()526 public void testUidIoStatsRecordDelta() throws Exception { 527 IoStatsEntry statEntry = new IoStatsEntry(10, 1000, 528 new IoStatsEntry.Metrics(10, 20, 30, 40, 50), 529 new IoStatsEntry.Metrics(60, 70, 80, 90, 100)); 530 531 UidIoRecord statRecord = new UidIoRecord(10, 532 20, 20, 30, 50, 70, 533 80, 70, 80, 100, 110); 534 535 UidIoRecord delta = statRecord.delta(statEntry); 536 537 assertThat(delta).isNotNull(); 538 assertThat(delta.uid).isEqualTo(statRecord.uid); 539 540 assertThat(delta.foreground_rchar).isEqualTo(10); 541 assertThat(delta.foreground_wchar).isEqualTo(0); 542 assertThat(delta.foreground_read_bytes).isEqualTo(0); 543 assertThat(delta.foreground_write_bytes).isEqualTo(10); 544 assertThat(delta.foreground_fsync).isEqualTo(20); 545 546 assertThat(delta.background_rchar).isEqualTo(20); 547 assertThat(delta.background_wchar).isEqualTo(0); 548 assertThat(delta.background_read_bytes).isEqualTo(0); 549 assertThat(delta.background_write_bytes).isEqualTo(10); 550 assertThat(delta.background_fsync).isEqualTo(10); 551 552 statRecord = new UidIoRecord(30, 553 20, 20, 30, 50, 70, 554 80, 70, 80, 100, 110); 555 556 try { 557 statRecord.delta(statEntry); 558 fail("delta only allowed on records for matching user ID"); 559 } catch (IllegalArgumentException e) { 560 // test passed 561 } 562 } 563 564 @Test 565 @SuppressWarnings("TruthSelfEquals") testUidIoStatsDelta()566 public void testUidIoStatsDelta() throws Exception { 567 IoStatsEntry entry10 = new IoStatsEntry(10, 1000, 568 new IoStatsEntry.Metrics(10, 20, 30, 40, 50), 569 new IoStatsEntry.Metrics(60, 70, 80, 90, 100)); 570 571 IoStatsEntry entry20 = new IoStatsEntry(20, 2000, 572 new IoStatsEntry.Metrics(200, 60, 100, 30, 40), 573 new IoStatsEntry.Metrics(20, 10, 20, 0, 0)); 574 575 IoStatsEntry entry30 = new IoStatsEntry(30, 2000, 576 new IoStatsEntry.Metrics(50, 100, 100, 30, 40), 577 new IoStatsEntry.Metrics(30, 0, 0, 0, 0)); 578 579 ArrayList<IoStatsEntry> statsEntries1 = new ArrayList<IoStatsEntry>() {{ 580 add(entry10); 581 add(entry20); 582 }}; 583 584 ArrayList<IoStatsEntry> statsEntries2 = new ArrayList<IoStatsEntry>() {{ 585 add(entry20); 586 add(entry30); 587 }}; 588 589 IoStats delta1 = new IoStats(statsEntries1, 5000); 590 IoStats delta2 = new IoStats(statsEntries1, 5000); 591 IoStats delta3 = new IoStats(statsEntries2, 3000); 592 IoStats delta4 = new IoStats(statsEntries1, 5000); 593 594 assertThat(delta1).isEqualTo(delta1); 595 assertThat(delta2).isEqualTo(delta1); 596 assertThat(delta1).isNotSameInstanceAs(delta3); 597 assertThat(delta3).isNotSameInstanceAs(delta4); 598 } 599 600 @Test testUidIoStatsTotals()601 public void testUidIoStatsTotals() throws Exception { 602 IoStatsEntry entry10 = new IoStatsEntry(10, 1000, 603 new IoStatsEntry.Metrics(20, 0, 10, 0, 0), 604 new IoStatsEntry.Metrics(10, 50, 0, 20, 2)); 605 606 IoStatsEntry entry20 = new IoStatsEntry(20, 1000, 607 new IoStatsEntry.Metrics(100, 200, 50, 200, 1), 608 new IoStatsEntry.Metrics(0, 30, 10, 0, 1)); 609 610 ArrayList<IoStatsEntry> statsEntries = new ArrayList<IoStatsEntry>() {{ 611 add(entry10); 612 add(entry20); 613 }}; 614 615 IoStats delta = new IoStats(statsEntries, 5000); 616 617 IoStatsEntry.Metrics foregroundTotals = delta.getForegroundTotals(); 618 IoStatsEntry.Metrics backgroundTotals = delta.getBackgroundTotals(); 619 IoStatsEntry.Metrics overallTotals = delta.getTotals(); 620 621 assertThat(foregroundTotals.bytesRead).isEqualTo(120); 622 assertThat(foregroundTotals.bytesWritten).isEqualTo(200); 623 assertThat(foregroundTotals.bytesReadFromStorage).isEqualTo(60); 624 assertThat(foregroundTotals.bytesWrittenToStorage).isEqualTo(200); 625 assertThat(foregroundTotals.fsyncCalls).isEqualTo(1); 626 627 628 assertThat(backgroundTotals.bytesRead).isEqualTo(10); 629 assertThat(backgroundTotals.bytesWritten).isEqualTo(80); 630 assertThat(backgroundTotals.bytesReadFromStorage).isEqualTo(10); 631 assertThat(backgroundTotals.bytesWrittenToStorage).isEqualTo(20); 632 assertThat(backgroundTotals.fsyncCalls).isEqualTo(3); 633 634 assertThat(overallTotals.bytesRead).isEqualTo(130); 635 assertThat(overallTotals.bytesWritten).isEqualTo(280); 636 assertThat(overallTotals.bytesReadFromStorage).isEqualTo(70); 637 assertThat(overallTotals.bytesWrittenToStorage).isEqualTo(220); 638 assertThat(overallTotals.fsyncCalls).isEqualTo(4); 639 } 640 641 @Test testUidIoStatsDeltaParcel()642 public void testUidIoStatsDeltaParcel() throws Exception { 643 IoStatsEntry entry10 = new IoStatsEntry(10, 1000, 644 new IoStatsEntry.Metrics(10, 20, 30, 40, 50), 645 new IoStatsEntry.Metrics(60, 70, 80, 90, 100)); 646 647 IoStatsEntry entry20 = new IoStatsEntry(20, 2000, 648 new IoStatsEntry.Metrics(200, 60, 100, 30, 40), 649 new IoStatsEntry.Metrics(20, 10, 20, 0, 0)); 650 651 ArrayList<IoStatsEntry> statsEntries = new ArrayList<IoStatsEntry>() {{ 652 add(entry10); 653 add(entry20); 654 }}; 655 656 IoStats statsDelta = new IoStats(statsEntries, 5000); 657 658 Parcel p = Parcel.obtain(); 659 statsDelta.writeToParcel(p, 0); 660 p.setDataPosition(0); 661 662 IoStats parceledStatsDelta = new IoStats(p); 663 664 assertThat(parceledStatsDelta.getTimestamp()).isEqualTo(statsDelta.getTimestamp()); 665 666 assertEquals(2, parceledStatsDelta.getStats().stream() 667 .filter(e -> e.equals(entry10) || e.equals(entry20)) 668 .count()); 669 } 670 671 @Test testUidIoStatsDeltaJson()672 public void testUidIoStatsDeltaJson() throws Exception { 673 try (TemporaryFile temporaryFile = new TemporaryFile(TAG)) { 674 IoStatsEntry entry10 = new IoStatsEntry(10, 1000, 675 new IoStatsEntry.Metrics(10, 20, 30, 40, 50), 676 new IoStatsEntry.Metrics(60, 70, 80, 90, 100)); 677 678 IoStatsEntry entry20 = new IoStatsEntry(20, 2000, 679 new IoStatsEntry.Metrics(200, 60, 100, 30, 40), 680 new IoStatsEntry.Metrics(20, 10, 20, 0, 0)); 681 682 ArrayList<IoStatsEntry> statsEntries = new ArrayList<IoStatsEntry>() {{ 683 add(entry10); 684 add(entry20); 685 }}; 686 687 IoStats statsDelta = new IoStats(statsEntries, 5000); 688 try (JsonWriter jsonWriter = new JsonWriter(new FileWriter(temporaryFile.getFile()))) { 689 statsDelta.writeToJson(jsonWriter); 690 } 691 JSONObject jsonObject = new JSONObject( 692 new String(Files.readAllBytes(temporaryFile.getPath()))); 693 IoStats other = new IoStats(jsonObject); 694 assertThat(other).isEqualTo(statsDelta); 695 } 696 } 697 698 @Test testLifetimeWriteInfo()699 public void testLifetimeWriteInfo() throws Exception { 700 try (TemporaryDirectory temporaryDirectory = new TemporaryDirectory(TAG)) { 701 try (TemporaryDirectory ext4 = temporaryDirectory.getSubdirectory("ext4"); 702 TemporaryDirectory f2fs = temporaryDirectory.getSubdirectory("f2fs")) { 703 try(TemporaryDirectory ext4_part1 = ext4.getSubdirectory("part1"); 704 TemporaryDirectory f2fs_part1 = f2fs.getSubdirectory("part1"); 705 TemporaryDirectory ext4_part2 = ext4.getSubdirectory("part2"); 706 TemporaryDirectory f2f2_notpart = f2fs.getSubdirectory("nopart")) { 707 Files.write(ext4_part1.getPath().resolve("lifetime_write_kbytes"), 708 Collections.singleton("123")); 709 Files.write(f2fs_part1.getPath().resolve("lifetime_write_kbytes"), 710 Collections.singleton("250")); 711 Files.write(ext4_part2.getPath().resolve("lifetime_write_kbytes"), 712 Collections.singleton("2147483660")); 713 714 LifetimeWriteInfo expected_ext4_part1 = 715 new LifetimeWriteInfo("part1", "ext4", 123*1024); 716 LifetimeWriteInfo expected_f2fs_part1 = 717 new LifetimeWriteInfo("part1", "f2fs", 250*1024); 718 LifetimeWriteInfo expected_ext4_part2 = 719 new LifetimeWriteInfo("part2", "ext4", 2147483660L*1024); 720 721 SysfsLifetimeWriteInfoProvider sysfsLifetimeWriteInfoProvider = 722 new SysfsLifetimeWriteInfoProvider(temporaryDirectory.getDirectory()); 723 724 LifetimeWriteInfo[] writeInfos = sysfsLifetimeWriteInfoProvider.load(); 725 726 assertThat(writeInfos).isNotNull(); 727 assertThat(writeInfos.length).isEqualTo(3); 728 assertTrue(Arrays.stream(writeInfos).anyMatch( 729 li -> li.equals(expected_ext4_part1))); 730 assertTrue(Arrays.stream(writeInfos).anyMatch( 731 li -> li.equals(expected_ext4_part2))); 732 assertTrue(Arrays.stream(writeInfos).anyMatch( 733 li -> li.equals(expected_f2fs_part1))); 734 } 735 } 736 } 737 } 738 739 @Test 740 @SuppressWarnings("TruthSelfEquals") testLifetimeWriteInfoEquality()741 public void testLifetimeWriteInfoEquality() throws Exception { 742 LifetimeWriteInfo writeInfo = new LifetimeWriteInfo("part1", "ext4", 123); 743 LifetimeWriteInfo writeInfoEq = new LifetimeWriteInfo("part1", "ext4", 123); 744 745 LifetimeWriteInfo writeInfoNeq1 = new LifetimeWriteInfo("part2", "ext4", 123); 746 LifetimeWriteInfo writeInfoNeq2 = new LifetimeWriteInfo("part1", "f2fs", 123); 747 LifetimeWriteInfo writeInfoNeq3 = new LifetimeWriteInfo("part1", "ext4", 100); 748 749 assertThat(writeInfo).isEqualTo(writeInfo); 750 assertThat(writeInfoEq).isEqualTo(writeInfo); 751 assertThat(writeInfo).isNotSameInstanceAs(writeInfoNeq1); 752 assertThat(writeInfo).isNotSameInstanceAs(writeInfoNeq2); 753 assertThat(writeInfo).isNotSameInstanceAs(writeInfoNeq3); 754 } 755 756 @Test testLifetimeWriteInfoParcel()757 public void testLifetimeWriteInfoParcel() throws Exception { 758 LifetimeWriteInfo lifetimeWriteInfo = new LifetimeWriteInfo("part1", "ext4", 1024); 759 760 Parcel p = Parcel.obtain(); 761 lifetimeWriteInfo.writeToParcel(p, 0); 762 p.setDataPosition(0); 763 764 LifetimeWriteInfo parceled = new LifetimeWriteInfo(p); 765 766 assertThat(parceled).isEqualTo(lifetimeWriteInfo); 767 } 768 769 @Test testLifetimeWriteInfoJson()770 public void testLifetimeWriteInfoJson() throws Exception { 771 try (TemporaryFile temporaryFile = new TemporaryFile(TAG)) { 772 LifetimeWriteInfo lifetimeWriteInfo = new LifetimeWriteInfo("part1", "ext4", 1024); 773 774 try (JsonWriter jsonWriter = new JsonWriter(new FileWriter(temporaryFile.getFile()))) { 775 lifetimeWriteInfo.writeToJson(jsonWriter); 776 } 777 JSONObject jsonObject = new JSONObject( 778 new String(Files.readAllBytes(temporaryFile.getPath()))); 779 LifetimeWriteInfo other = new LifetimeWriteInfo(jsonObject); 780 assertThat(other).isEqualTo(lifetimeWriteInfo); 781 } 782 } 783 } 784