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.car.internal.property;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.junit.Assert.assertThrows;
22 import static org.mockito.Mockito.mock;
23 import static org.mockito.Mockito.when;
24 
25 import android.car.VehicleAreaType;
26 import android.car.feature.FeatureFlags;
27 import android.car.hardware.CarPropertyConfig;
28 import android.car.hardware.property.AreaIdConfig;
29 
30 import org.junit.Test;
31 import org.junit.runner.RunWith;
32 import org.mockito.junit.MockitoJUnitRunner;
33 
34 import java.util.List;
35 
36 @RunWith(MockitoJUnitRunner.class)
37 public final class InputSanitizationUtilsUnitTest {
38     private static final int PROPERTY_ID = 123;
39     private static final float DEFAULT_UPDATE_RATE_HZ = 55.5f;
40     private static final float MIN_UPDATE_RATE_HZ = 11.11f;
41     private static final float MAX_UPDATE_RATE_HZ = 100.3f;
42     private static final CarPropertyConfig.Builder<Integer> CAR_PROPERTY_CONFIG_BUILDER =
43             CarPropertyConfig.newBuilder(
44                     Integer.class, PROPERTY_ID, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
45 
46     @Test
sanitizeUpdateRateHz_returnsZeroForStaticProperties()47     public void sanitizeUpdateRateHz_returnsZeroForStaticProperties() {
48         assertThat(
49                         InputSanitizationUtils.sanitizeUpdateRateHz(
50                                 CAR_PROPERTY_CONFIG_BUILDER
51                                         .setChangeMode(
52                                                 CarPropertyConfig
53                                                         .VEHICLE_PROPERTY_CHANGE_MODE_STATIC)
54                                         .build(),
55                                 DEFAULT_UPDATE_RATE_HZ))
56                 .isEqualTo(0);
57     }
58 
59     @Test
sanitizeUpdateRateHz_returnsZeroForOnChangeProperties()60     public void sanitizeUpdateRateHz_returnsZeroForOnChangeProperties() {
61         assertThat(
62                         InputSanitizationUtils.sanitizeUpdateRateHz(
63                                 CAR_PROPERTY_CONFIG_BUILDER
64                                         .setChangeMode(
65                                                 CarPropertyConfig
66                                                         .VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE)
67                                         .build(),
68                                 DEFAULT_UPDATE_RATE_HZ))
69                 .isEqualTo(0);
70     }
71 
72     @Test
sanitizeUpdateRateHz_returnsMaxUpdateRateHzIfOver()73     public void sanitizeUpdateRateHz_returnsMaxUpdateRateHzIfOver() {
74         assertThat(
75                         InputSanitizationUtils.sanitizeUpdateRateHz(
76                                 CAR_PROPERTY_CONFIG_BUILDER
77                                         .setChangeMode(
78                                                 CarPropertyConfig
79                                                         .VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS)
80                                         .setMinSampleRate(MIN_UPDATE_RATE_HZ)
81                                         .setMaxSampleRate(MAX_UPDATE_RATE_HZ)
82                                         .build(),
83                                 MAX_UPDATE_RATE_HZ + 1))
84                 .isEqualTo(MAX_UPDATE_RATE_HZ);
85     }
86 
87     @Test
sanitizeUpdateRateHz_returnsMinUpdateRateHzIfOver()88     public void sanitizeUpdateRateHz_returnsMinUpdateRateHzIfOver() {
89         assertThat(
90                         InputSanitizationUtils.sanitizeUpdateRateHz(
91                                 CAR_PROPERTY_CONFIG_BUILDER
92                                         .setChangeMode(
93                                                 CarPropertyConfig
94                                                         .VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS)
95                                         .setMinSampleRate(MIN_UPDATE_RATE_HZ)
96                                         .setMaxSampleRate(MAX_UPDATE_RATE_HZ)
97                                         .build(),
98                                 MIN_UPDATE_RATE_HZ - 1))
99                 .isEqualTo(MIN_UPDATE_RATE_HZ);
100     }
101 
102     @Test
sanitizeUpdateRateHz_returnsDefaultUpdateRateHz()103     public void sanitizeUpdateRateHz_returnsDefaultUpdateRateHz() {
104         assertThat(
105                         InputSanitizationUtils.sanitizeUpdateRateHz(
106                                 CAR_PROPERTY_CONFIG_BUILDER
107                                         .setChangeMode(
108                                                 CarPropertyConfig
109                                                         .VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS)
110                                         .setMinSampleRate(MIN_UPDATE_RATE_HZ)
111                                         .setMaxSampleRate(MAX_UPDATE_RATE_HZ)
112                                         .build(),
113                                 DEFAULT_UPDATE_RATE_HZ))
114                 .isEqualTo(DEFAULT_UPDATE_RATE_HZ);
115     }
116 
117     @Test
testIsVurAllowed()118     public void testIsVurAllowed() {
119         CarPropertyConfig config = mock(CarPropertyConfig.class);
120         when(config.getChangeMode()).thenReturn(
121                 CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS);
122         FeatureFlags featureFlags = mock(FeatureFlags.class);
123         when(featureFlags.variableUpdateRate()).thenReturn(true);
124 
125         assertThat(InputSanitizationUtils.isVurAllowed(featureFlags, config)).isTrue();
126     }
127 
128     @Test
testIsVurAllowed_featureDisabled()129     public void testIsVurAllowed_featureDisabled() {
130         CarPropertyConfig config = mock(CarPropertyConfig.class);
131         when(config.getChangeMode()).thenReturn(
132                 CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS);
133         FeatureFlags featureFlags = mock(FeatureFlags.class);
134         when(featureFlags.variableUpdateRate()).thenReturn(false);
135 
136         assertThat(InputSanitizationUtils.isVurAllowed(featureFlags, config)).isFalse();
137     }
138 
139     @Test
testIsVurAllowed_propertyNotContinuous()140     public void testIsVurAllowed_propertyNotContinuous() {
141         CarPropertyConfig config = mock(CarPropertyConfig.class);
142         when(config.getChangeMode()).thenReturn(
143                 CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE);
144         FeatureFlags featureFlags = mock(FeatureFlags.class);
145         when(featureFlags.variableUpdateRate()).thenReturn(true);
146 
147         assertThat(InputSanitizationUtils.isVurAllowed(featureFlags, config)).isFalse();
148     }
149 
150     @Test
testSanitizeEnableVariableUpdateRate()151     public void testSanitizeEnableVariableUpdateRate() {
152         CarSubscription inputOption = newCarSubscription(PROPERTY_ID, new int[]{1, 2, 3},
153                 DEFAULT_UPDATE_RATE_HZ, true);
154 
155         FeatureFlags featureFlags = mock(FeatureFlags.class);
156         when(featureFlags.variableUpdateRate()).thenReturn(true);
157         CarPropertyConfig config = mock(CarPropertyConfig.class);
158         when(config.getChangeMode()).thenReturn(
159                 CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS);
160         AreaIdConfig areaIdConfigEnabled = mock(AreaIdConfig.class);
161         when(areaIdConfigEnabled.isVariableUpdateRateSupported()).thenReturn(true);
162         AreaIdConfig areaIdConfigDisabled = mock(AreaIdConfig.class);
163         when(areaIdConfigDisabled.isVariableUpdateRateSupported()).thenReturn(false);
164         when(config.getAreaIdConfig(1)).thenReturn(areaIdConfigEnabled);
165         when(config.getAreaIdConfig(2)).thenThrow(new IllegalArgumentException());
166         when(config.getAreaIdConfig(3)).thenReturn(areaIdConfigDisabled);
167 
168         List<CarSubscription> sanitizedOptions =
169                 InputSanitizationUtils.sanitizeEnableVariableUpdateRate(featureFlags, config,
170                 inputOption);
171 
172         assertThat(sanitizedOptions).containsExactly(
173                 newCarSubscription(PROPERTY_ID, new int[]{1}, DEFAULT_UPDATE_RATE_HZ, true),
174                 newCarSubscription(PROPERTY_ID, new int[]{2, 3}, DEFAULT_UPDATE_RATE_HZ, false));
175     }
176 
177     @Test
testSanitizeResolution()178     public void testSanitizeResolution() {
179         FeatureFlags featureFlags = mock(FeatureFlags.class);
180         CarPropertyConfig config = mock(CarPropertyConfig.class);
181         when(config.getChangeMode()).thenReturn(
182                 CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE);
183         when(featureFlags.subscriptionWithResolution()).thenReturn(false);
184 
185         assertThat(InputSanitizationUtils.sanitizeResolution(featureFlags,
186                 config, 123.456f)).isEqualTo(0.0f);
187 
188         when(featureFlags.subscriptionWithResolution()).thenReturn(true);
189         assertThat(InputSanitizationUtils.sanitizeResolution(featureFlags,
190                 config, 123.456f)).isEqualTo(0.0f);
191 
192         when(config.getChangeMode()).thenReturn(
193                 CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS);
194         assertThat(InputSanitizationUtils.sanitizeResolution(featureFlags,
195                 config, 0.0f)).isEqualTo(0.0f);
196         assertThat(InputSanitizationUtils.sanitizeResolution(featureFlags,
197                 config, 0.1f)).isEqualTo(0.1f);
198         assertThat(InputSanitizationUtils.sanitizeResolution(featureFlags,
199                 config, 1.0f)).isEqualTo(1.0f);
200         assertThrows(IllegalArgumentException.class,
201                 () -> InputSanitizationUtils.sanitizeResolution(featureFlags,
202                         config, 2.0f));
203     }
204 
newCarSubscription(int propertyId, int[] areaIds, float updateRateHz, boolean enableVur)205     private static CarSubscription newCarSubscription(int propertyId, int[] areaIds,
206             float updateRateHz, boolean enableVur) {
207         CarSubscription option = new CarSubscription();
208         option.propertyId = propertyId;
209         option.areaIds = areaIds;
210         option.updateRateHz = updateRateHz;
211         option.enableVariableUpdateRate = enableVur;
212         return option;
213     }
214 }
215