CarStorageMonitoringTest.java revision b19bc326413285806ecca7fb7b54ec7a9074f286
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
17package com.android.car;
18
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.car.Car;
22import android.car.storagemonitoring.CarStorageMonitoringManager;
23import android.car.storagemonitoring.WearEstimate;
24import android.car.storagemonitoring.WearEstimateChange;
25import android.test.suitebuilder.annotation.MediumTest;
26import android.util.JsonWriter;
27import android.util.Log;
28import android.util.Pair;
29import com.android.car.storagemonitoring.WearEstimateRecord;
30import com.android.car.storagemonitoring.WearHistory;
31import com.android.car.storagemonitoring.WearInformation;
32import com.android.car.storagemonitoring.WearInformationProvider;
33import com.android.car.systeminterface.StorageMonitoringInterface;
34import com.android.car.systeminterface.SystemInterface;
35import com.android.car.systeminterface.SystemStateInterface;
36import com.android.car.systeminterface.TimeInterface;
37import java.io.File;
38import java.io.FileWriter;
39import java.io.IOException;
40import java.time.Duration;
41import java.time.Instant;
42import java.util.ArrayList;
43import java.util.Comparator;
44import java.util.HashMap;
45import java.util.List;
46import java.util.Map;
47
48/** Test the public entry points for the CarStorageMonitoringManager */
49@MediumTest
50public class CarStorageMonitoringTest extends MockedCarTestBase {
51    private static final String TAG = CarStorageMonitoringTest.class.getSimpleName();
52
53    private static final WearInformation DEFAULT_WEAR_INFORMATION =
54        new WearInformation(30, 0, WearInformation.PRE_EOL_INFO_NORMAL);
55
56    private static final class WearData {
57        static final WearData DEFAULT = new WearData(0, DEFAULT_WEAR_INFORMATION, null);
58
59        final long uptime;
60        @NonNull
61        final WearInformation wearInformation;
62        @Nullable
63        final WearHistory wearHistory;
64
65        WearData(long uptime, @Nullable WearInformation wearInformation, @Nullable WearHistory wearHistory) {
66            if (wearInformation == null) wearInformation = DEFAULT_WEAR_INFORMATION;
67            this.uptime = uptime;
68            this.wearInformation = wearInformation;
69            this.wearHistory = wearHistory;
70        }
71    }
72
73    private static final Map<String, WearData> PER_TEST_WEAR_DATA =
74            new HashMap<String, WearData>() {{
75                put("testReadWearHistory",
76                    new WearData(6500, DEFAULT_WEAR_INFORMATION,
77                        WearHistory.fromRecords(
78                            WearEstimateRecord.Builder.newBuilder()
79                                .fromWearEstimate(WearEstimate.UNKNOWN_ESTIMATE)
80                                .toWearEstimate(new WearEstimate(10, 0))
81                                .atUptime(1000)
82                                .atTimestamp(Instant.ofEpochMilli(5000)).build(),
83                            WearEstimateRecord.Builder.newBuilder()
84                                .fromWearEstimate(new WearEstimate(10, 0))
85                                .toWearEstimate(new WearEstimate(20, 0))
86                                .atUptime(4000)
87                                .atTimestamp(Instant.ofEpochMilli(12000)).build(),
88                            WearEstimateRecord.Builder.newBuilder()
89                                .fromWearEstimate(new WearEstimate(20, 0))
90                                .toWearEstimate(new WearEstimate(30, 0))
91                                .atUptime(6500)
92                                .atTimestamp(Instant.ofEpochMilli(17000)).build())));
93
94                put("testNotAcceptableWearEvent",
95                    new WearData(2520006499L,
96                        new WearInformation(40, 0, WearInformation.PRE_EOL_INFO_NORMAL),
97                        WearHistory.fromRecords(
98                            WearEstimateRecord.Builder.newBuilder()
99                                .fromWearEstimate(WearEstimate.UNKNOWN_ESTIMATE)
100                                .toWearEstimate(new WearEstimate(10, 0))
101                                .atUptime(1000)
102                                .atTimestamp(Instant.ofEpochMilli(5000)).build(),
103                            WearEstimateRecord.Builder.newBuilder()
104                                .fromWearEstimate(new WearEstimate(10, 0))
105                                .toWearEstimate(new WearEstimate(20, 0))
106                                .atUptime(4000)
107                                .atTimestamp(Instant.ofEpochMilli(12000)).build(),
108                            WearEstimateRecord.Builder.newBuilder()
109                                .fromWearEstimate(new WearEstimate(20, 0))
110                                .toWearEstimate(new WearEstimate(30, 0))
111                                .atUptime(6500)
112                                .atTimestamp(Instant.ofEpochMilli(17000)).build())));
113
114                put("testAcceptableWearEvent",
115                    new WearData(2520006501L,
116                        new WearInformation(40, 0, WearInformation.PRE_EOL_INFO_NORMAL),
117                        WearHistory.fromRecords(
118                            WearEstimateRecord.Builder.newBuilder()
119                                .fromWearEstimate(WearEstimate.UNKNOWN_ESTIMATE)
120                                .toWearEstimate(new WearEstimate(10, 0))
121                                .atUptime(1000)
122                                .atTimestamp(Instant.ofEpochMilli(5000)).build(),
123                            WearEstimateRecord.Builder.newBuilder()
124                                .fromWearEstimate(new WearEstimate(10, 0))
125                                .toWearEstimate(new WearEstimate(20, 0))
126                                .atUptime(4000)
127                                .atTimestamp(Instant.ofEpochMilli(12000)).build(),
128                            WearEstimateRecord.Builder.newBuilder()
129                                .fromWearEstimate(new WearEstimate(20, 0))
130                                .toWearEstimate(new WearEstimate(30, 0))
131                                .atUptime(6500)
132                                .atTimestamp(Instant.ofEpochMilli(17000)).build())));
133            }};
134
135    private final MockSystemStateInterface mMockSystemStateInterface =
136            new MockSystemStateInterface();
137    private final MockStorageMonitoringInterface mMockStorageMonitoringInterface =
138            new MockStorageMonitoringInterface();
139
140    private CarStorageMonitoringManager mCarStorageMonitoringManager;
141
142    @Override
143    protected synchronized SystemInterface.Builder getSystemInterfaceBuilder() {
144        SystemInterface.Builder builder = super.getSystemInterfaceBuilder();
145        return builder.withSystemStateInterface(mMockSystemStateInterface)
146            .withStorageMonitoringInterface(mMockStorageMonitoringInterface)
147            .withTimeInterface(new MockTimeInterface());
148    }
149
150    @Override
151    protected synchronized void configureFakeSystemInterface() {
152        try {
153            final String testName = getName();
154            final WearData wearData = PER_TEST_WEAR_DATA.getOrDefault(testName, WearData.DEFAULT);
155            final WearHistory wearHistory = wearData.wearHistory;
156
157            mMockStorageMonitoringInterface.setWearInformation(wearData.wearInformation);
158
159            if (wearHistory != null) {
160                File wearHistoryFile = new File(getFakeSystemInterface().getFilesDir(),
161                    CarStorageMonitoringService.WEAR_INFO_FILENAME);
162                try (JsonWriter jsonWriter = new JsonWriter(new FileWriter(wearHistoryFile))) {
163                    wearHistory.writeToJson(jsonWriter);
164                }
165            }
166
167            if (wearData.uptime > 0) {
168                File uptimeFile = new File(getFakeSystemInterface().getFilesDir(),
169                    CarStorageMonitoringService.UPTIME_TRACKER_FILENAME);
170                try (JsonWriter jsonWriter = new JsonWriter(new FileWriter(uptimeFile))) {
171                    jsonWriter.beginObject();
172                    jsonWriter.name("uptime").value(wearData.uptime);
173                    jsonWriter.endObject();
174                }
175            }
176        } catch (IOException e) {
177            Log.e(TAG, "failed to configure fake system interface", e);
178            fail("failed to configure fake system interface instance");
179        }
180
181    }
182
183    @Override
184    protected void setUp() throws Exception {
185        super.setUp();
186
187        mMockSystemStateInterface.executeBootCompletedActions();
188
189        mCarStorageMonitoringManager =
190            (CarStorageMonitoringManager) getCar().getCarManager(Car.STORAGE_MONITORING_SERVICE);
191    }
192
193    public void testReadPreEolInformation() throws Exception {
194        assertEquals(DEFAULT_WEAR_INFORMATION.preEolInfo,
195                mCarStorageMonitoringManager.getPreEolIndicatorStatus());
196    }
197
198    public void testReadWearEstimate() throws Exception {
199        final WearEstimate wearEstimate = mCarStorageMonitoringManager.getWearEstimate();
200
201        assertNotNull(wearEstimate);
202        assertEquals(DEFAULT_WEAR_INFORMATION.lifetimeEstimateA, wearEstimate.typeA);
203        assertEquals(DEFAULT_WEAR_INFORMATION.lifetimeEstimateB, wearEstimate.typeB);
204    }
205
206    public void testReadWearHistory() throws Exception {
207        final List<WearEstimateChange> wearEstimateChanges =
208                mCarStorageMonitoringManager.getWearEstimateHistory();
209
210        assertNotNull(wearEstimateChanges);
211        assertFalse(wearEstimateChanges.isEmpty());
212
213        final WearHistory expectedWearHistory = PER_TEST_WEAR_DATA.get(getName()).wearHistory;
214
215        assertEquals(expectedWearHistory.size(), wearEstimateChanges.size());
216        for (int i = 0; i < wearEstimateChanges.size(); ++i) {
217            final WearEstimateRecord expected = expectedWearHistory.get(i);
218            final WearEstimateChange actual = wearEstimateChanges.get(i);
219
220            assertTrue(expected.isSameAs(actual));
221        }
222    }
223
224    private void checkLastWearEvent(boolean isAcceptable) throws Exception {
225        final List<WearEstimateChange> wearEstimateChanges =
226            mCarStorageMonitoringManager.getWearEstimateHistory();
227
228        assertNotNull(wearEstimateChanges);
229        assertFalse(wearEstimateChanges.isEmpty());
230
231        final WearData wearData = PER_TEST_WEAR_DATA.get(getName());
232
233        final WearInformation expectedCurrentWear = wearData.wearInformation;
234        final WearEstimate expectedPreviousWear = wearData.wearHistory.getLast().getNewWearEstimate();
235
236        final WearEstimateChange actualCurrentWear =
237                wearEstimateChanges.get(wearEstimateChanges.size() - 1);
238
239        assertEquals(isAcceptable, actualCurrentWear.isAcceptableDegradation);
240        assertEquals(expectedCurrentWear.toWearEstimate(), actualCurrentWear.newEstimate);
241        assertEquals(expectedPreviousWear, actualCurrentWear.oldEstimate);
242    }
243
244    public void testNotAcceptableWearEvent() throws Exception {
245        checkLastWearEvent(false);
246    }
247
248    public void testAcceptableWearEvent() throws Exception {
249        checkLastWearEvent(true);
250    }
251
252    static final class MockStorageMonitoringInterface implements StorageMonitoringInterface,
253        WearInformationProvider {
254        private WearInformation mWearInformation = null;
255
256        void setWearInformation(WearInformation wearInformation) {
257            mWearInformation = wearInformation;
258        }
259
260        @Override
261        public WearInformation load() {
262            return mWearInformation;
263        }
264
265        @Override
266        public WearInformationProvider[] getFlashWearInformationProviders() {
267            return new WearInformationProvider[] {this};
268        }
269    }
270
271    static final class MockTimeInterface implements TimeInterface {
272
273        @Override
274        public long getUptime(boolean includeDeepSleepTime) {
275            return 0;
276        }
277
278        @Override
279        public void scheduleAction(Runnable r, long delayMs) {}
280
281        @Override
282        public void cancelAllActions() {}
283    }
284
285    static final class MockSystemStateInterface implements SystemStateInterface {
286        private final List<Pair<Runnable, Duration>> mActionsList = new ArrayList<>();
287
288        @Override
289        public void shutdown() {}
290
291        @Override
292        public void enterDeepSleep(int wakeupTimeSec) {}
293
294        @Override
295        public void scheduleActionForBootCompleted(Runnable action, Duration delay) {
296            mActionsList.add(Pair.create(action, delay));
297            mActionsList.sort(Comparator.comparing(d -> d.second));
298        }
299
300        void executeBootCompletedActions() {
301            for (Pair<Runnable, Duration> action : mActionsList) {
302                action.first.run();
303            }
304        }
305    }
306}
307