blob: d54e734c78c4bc645f9fe73dc37bff4983e0f65d [file] [log] [blame]
Lakshman Annadorai282c3ce2021-08-17 09:08:27 -07001/*
2 * Copyright (C) 2021 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
17package com.android.car.watchdog;
18
19import static com.google.common.truth.Truth.assertAbout;
20import static com.google.common.truth.Truth.assertWithMessage;
21
22import android.annotation.Nullable;
23import android.automotive.watchdog.IoOveruseStats;
24import android.automotive.watchdog.PerStateBytes;
25
26import com.google.common.truth.Correspondence;
27import com.google.common.truth.FailureMetadata;
28import com.google.common.truth.Subject;
29
30import java.util.Arrays;
31
32public final class IoUsageStatsEntrySubject extends Subject {
33 /* Boiler-plate Subject.Factory for IoUsageStatsEntrySubject. */
34 private static final Subject.Factory<
35 com.android.car.watchdog.IoUsageStatsEntrySubject,
36 Iterable<WatchdogStorage.IoUsageStatsEntry>> IO_OVERUSE_STATS_ENTRY_SUBJECT_FACTORY =
37 com.android.car.watchdog.IoUsageStatsEntrySubject::new;
38 private static final String NULL_ENTRY_STRING = "{NULL}";
39
40 private final Iterable<WatchdogStorage.IoUsageStatsEntry> mActual;
41
42 /* User-defined entry point. */
43 public static IoUsageStatsEntrySubject assertThat(
44 @Nullable Iterable<WatchdogStorage.IoUsageStatsEntry> stats) {
45 return assertAbout(IO_OVERUSE_STATS_ENTRY_SUBJECT_FACTORY).that(stats);
46 }
47
48 public static Subject.Factory<IoUsageStatsEntrySubject,
Lakshman Annadorai64d0e1f2021-10-06 12:19:41 -070049 Iterable<WatchdogStorage.IoUsageStatsEntry>> ioUsageStatsEntries() {
Lakshman Annadorai282c3ce2021-08-17 09:08:27 -070050 return IO_OVERUSE_STATS_ENTRY_SUBJECT_FACTORY;
51 }
52
53 public void containsExactly(WatchdogStorage.IoUsageStatsEntry... stats) {
54 containsExactlyElementsIn(Arrays.asList(stats));
55 }
56
57 public void containsExactlyElementsIn(Iterable<WatchdogStorage.IoUsageStatsEntry> expected) {
58 assertWithMessage("Expected stats(%s) equals to actual stats(%s)", toString(expected),
59 toString(mActual)).that(mActual)
60 .comparingElementsUsing(Correspondence.from(
61 IoUsageStatsEntrySubject::isEquals, "is equal to"))
62 .containsExactlyElementsIn(expected);
63 }
64
65 public static boolean isEquals(WatchdogStorage.IoUsageStatsEntry actual,
66 WatchdogStorage.IoUsageStatsEntry expected) {
67 if (actual == null || expected == null) {
68 return (actual == null) && (expected == null);
69 }
70 return actual.userId == expected.userId && actual.packageName.equals(expected.packageName)
71 && actual.ioUsage.getTotalTimesKilled() == expected.ioUsage.getTotalTimesKilled()
72 && isEqualsPerStateBytes(actual.ioUsage.getForgivenWriteBytes(),
73 expected.ioUsage.getForgivenWriteBytes())
74 && isEqualsIoOveruseStats(actual.ioUsage.getInternalIoOveruseStats(),
75 expected.ioUsage.getInternalIoOveruseStats());
76 }
77
78 private static boolean isEqualsIoOveruseStats(android.automotive.watchdog.IoOveruseStats actual,
79 android.automotive.watchdog.IoOveruseStats expected) {
80 if (actual == null || expected == null) {
81 return (actual == null) && (expected == null);
82 }
83 return actual.killableOnOveruse == expected.killableOnOveruse
84 && isEqualsPerStateBytes(actual.remainingWriteBytes, expected.remainingWriteBytes)
85 && actual.startTime == expected.startTime
86 && actual.durationInSeconds == expected.durationInSeconds
87 && isEqualsPerStateBytes(actual.writtenBytes, expected.writtenBytes)
88 && actual.totalOveruses == expected.totalOveruses;
89 }
90
91 private static boolean isEqualsPerStateBytes(PerStateBytes actual, PerStateBytes expected) {
92 if (actual == null || expected == null) {
93 return (actual == null) && (expected == null);
94 }
95 return actual.foregroundBytes == expected.foregroundBytes
96 && actual.backgroundBytes == expected.backgroundBytes
97 && actual.garageModeBytes == expected.garageModeBytes;
98 }
99
100 private static String toString(Iterable<WatchdogStorage.IoUsageStatsEntry> entries) {
101 StringBuilder builder = new StringBuilder();
102 builder.append('[');
103 for (WatchdogStorage.IoUsageStatsEntry entry : entries) {
104 toStringBuilder(builder, entry).append(", ");
105 }
106 if (builder.length() > 1) {
107 builder.delete(builder.length() - 2, builder.length());
108 }
109 builder.append(']');
110 return builder.toString();
111 }
112
113 private static StringBuilder toStringBuilder(StringBuilder builder,
114 WatchdogStorage.IoUsageStatsEntry entry) {
115 builder.append("{UserId: ").append(entry.userId)
116 .append(", Package name: ").append(entry.packageName)
117 .append(", IoUsage: ");
118 toStringBuilder(builder, entry.ioUsage);
119 return builder.append('}');
120 }
121
122 private static StringBuilder toStringBuilder(StringBuilder builder,
123 WatchdogPerfHandler.PackageIoUsage ioUsage) {
124 builder.append("{IoOveruseStats: ");
125 toStringBuilder(builder, ioUsage.getInternalIoOveruseStats());
126 builder.append(", ForgivenWriteBytes: ");
127 toStringBuilder(builder, ioUsage.getForgivenWriteBytes());
128 return builder.append(", Total times killed: ").append(ioUsage.getTotalTimesKilled())
129 .append('}');
130 }
131
132 private static StringBuilder toStringBuilder(StringBuilder builder,
133 IoOveruseStats stats) {
134 if (stats == null) {
135 return builder.append(NULL_ENTRY_STRING);
136 }
137 builder.append("{Killable on overuse: ").append(stats.killableOnOveruse)
138 .append(", Remaining write bytes: ");
139 toStringBuilder(builder, stats.remainingWriteBytes);
140 builder.append(", Start time: ").append(stats.startTime)
141 .append(", Duration: ").append(stats.durationInSeconds).append(" seconds")
142 .append(", Total overuses: ").append(stats.totalOveruses)
143 .append(", Written bytes: ");
144 toStringBuilder(builder, stats.writtenBytes);
145 return builder.append('}');
146 }
147
148 private static StringBuilder toStringBuilder(
149 StringBuilder builder, PerStateBytes perStateBytes) {
150 if (perStateBytes == null) {
151 return builder.append(NULL_ENTRY_STRING);
152 }
153 return builder.append("{Foreground bytes: ").append(perStateBytes.foregroundBytes)
154 .append(", Background bytes: ").append(perStateBytes.backgroundBytes)
155 .append(", Garage mode bytes: ").append(perStateBytes.garageModeBytes)
156 .append('}');
157 }
158
159 private IoUsageStatsEntrySubject(FailureMetadata failureMetadata,
160 @Nullable Iterable<WatchdogStorage.IoUsageStatsEntry> iterableSubject) {
161 super(failureMetadata, iterableSubject);
162
163 mActual = iterableSubject;
164 }
165}