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