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.hal.fakevhal;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.junit.Assert.assertThrows;
22 
23 import android.hardware.automotive.vehicle.AccessForVehicleProperty;
24 import android.hardware.automotive.vehicle.ChangeModeForVehicleProperty;
25 import android.hardware.automotive.vehicle.RawPropValues;
26 import android.hardware.automotive.vehicle.VehicleAreaConfig;
27 import android.hardware.automotive.vehicle.VehicleAreaDoor;
28 import android.hardware.automotive.vehicle.VehicleAreaSeat;
29 import android.hardware.automotive.vehicle.VehicleAreaWheel;
30 import android.hardware.automotive.vehicle.VehiclePropConfig;
31 import android.hardware.automotive.vehicle.VehicleProperty;
32 import android.hardware.automotive.vehicle.VehiclePropertyAccess;
33 import android.hardware.automotive.vehicle.VehiclePropertyChangeMode;
34 import android.hardware.automotive.vehicle.VehicleSeatOccupancyState;
35 import android.hardware.automotive.vehicle.VehicleUnit;
36 import android.util.SparseArray;
37 
38 import androidx.test.filters.SmallTest;
39 
40 import org.junit.Before;
41 import org.junit.Test;
42 
43 import java.io.File;
44 import java.io.FileInputStream;
45 import java.io.FileOutputStream;
46 import java.io.IOException;
47 import java.io.InputStream;
48 
49 @SmallTest
50 public class FakeVhalConfigParserUnitTest {
51     private static final int DOOR_1_LEFT = VehicleAreaDoor.ROW_1_LEFT;
52     private static final int WHEEL_FRONT_LEFT = VehicleAreaWheel.LEFT_FRONT;
53 
54     private FakeVhalConfigParser mFakeVhalConfigParser;
55 
56     @Before
setUp()57     public void setUp() {
58         mFakeVhalConfigParser = new FakeVhalConfigParser();
59     }
60 
61     @Test
testDefaultConfigFileIsEmpty()62     public void testDefaultConfigFileIsEmpty() throws Exception {
63         InputStream tempFileIS =
64                 new FileInputStream(createTempFileWithContent(/* fileContent= */ ""));
65 
66         assertThrows(IOException.class,
67                 () -> mFakeVhalConfigParser.parseJsonConfig(tempFileIS));
68     }
69 
70     @Test
testCustomConfigFileNotExist()71     public void testCustomConfigFileNotExist() throws Exception {
72         File tempFile = new File("NotExist.json");
73 
74         SparseArray<ConfigDeclaration> result = mFakeVhalConfigParser.parseJsonConfig(tempFile);
75 
76         assertThat(result.size()).isEqualTo(0);
77     }
78 
79     @Test
testCustomConfigFileIsEmpty()80     public void testCustomConfigFileIsEmpty() throws Exception {
81         File tempFile = createTempFileWithContent(/* fileContent= */ "");
82 
83         SparseArray<ConfigDeclaration> result = mFakeVhalConfigParser.parseJsonConfig(tempFile);
84 
85         assertThat(result.size()).isEqualTo(0);
86     }
87 
88     @Test
testConfigFileHaveInvalidJsonObject()89     public void testConfigFileHaveInvalidJsonObject() throws Exception {
90         String fileContent = "This is a config file.";
91         File tempFile = createTempFileWithContent(fileContent);
92 
93         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class,
94                 () -> mFakeVhalConfigParser.parseJsonConfig(tempFile));
95 
96         assertThat(thrown).hasMessageThat().contains("This file does not contain a valid "
97                 + "JSONObject.");
98     }
99 
100     @Test
testConfigFileInvalidJsonKey()101     public void testConfigFileInvalidJsonKey() throws Exception {
102         String jsonString = "{[]: 123}";
103         File tempFile = createTempFileWithContent(jsonString);
104 
105         var thrown = assertThrows(IllegalArgumentException.class, () ->
106                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
107 
108         assertThat(thrown).hasMessageThat().contains("Invalid json syntax");
109     }
110 
111     @Test
testConfigFileRootIsNotArray()112     public void testConfigFileRootIsNotArray() throws Exception {
113         String jsonString = "{\"properties\": 123}";
114         File tempFile = createTempFileWithContent(jsonString);
115 
116         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
117                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
118 
119         assertThat(thrown).hasMessageThat().contains("field value is not a valid JSONArray.");
120     }
121 
122     @Test
testConfigFileRootHasElementIsNotJsonObject()123     public void testConfigFileRootHasElementIsNotJsonObject() throws Exception {
124         String jsonString = "{\"properties\": [{}, 123]}";
125         File tempFile = createTempFileWithContent(jsonString);
126 
127         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
128                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
129 
130         assertThat(thrown).hasMessageThat().contains("properties array has an invalid JSON element"
131                 + " at index 1");
132     }
133 
134     @Test
testParseEachPropertyJsonObjectIsEmpty()135     public void testParseEachPropertyJsonObjectIsEmpty() throws Exception {
136         String jsonString = "{\"properties\": [{}]}";
137         File tempFile = createTempFileWithContent(jsonString);
138 
139         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
140                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
141 
142         assertThat(thrown).hasMessageThat().contains("is empty");
143     }
144 
145     @Test
testParsePropertyIdWithIntValue()146     public void testParsePropertyIdWithIntValue() throws Exception {
147         String jsonString = "{\"properties\": [{\"property\": 123,"
148                 + "\"access\": \"VehiclePropertyAccess::READ_WRITE\","
149                 + "\"changeMode\": \"VehiclePropertyChangeMode::STATIC\"}]}";
150         File tempFile = createTempFileWithContent(jsonString);
151 
152         int propId = mFakeVhalConfigParser.parseJsonConfig(tempFile)
153                 .get(123).getConfig().prop;
154 
155         assertThat(propId).isEqualTo(123);
156     }
157 
158     @Test
testParsePropertyIdFieldNotExist()159     public void testParsePropertyIdFieldNotExist() throws Exception {
160         String jsonString = "{\"properties\": [{\"NotAPropIdFieldName\": 123}]}";
161         File tempFile = createTempFileWithContent(jsonString);
162 
163         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
164                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
165 
166         assertThat(thrown).hasMessageThat().contains("PropId is required");
167     }
168 
169     @Test
testParsePropertyIdValueNull()170     public void testParsePropertyIdValueNull() throws Exception {
171         String jsonString = "{\"properties\": [{\"property\": NULL}]}";
172         File tempFile = createTempFileWithContent(jsonString);
173 
174         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
175                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
176 
177         assertThat(thrown).hasMessageThat().contains("property doesn't have a valid int value.");
178     }
179 
180     @Test
testParsePropertyIdWithWrongValueType()181     public void testParsePropertyIdWithWrongValueType() throws Exception {
182         String jsonString = "{\"properties\": [{\"property\": 12.3}]}";
183         File tempFile = createTempFileWithContent(jsonString);
184 
185         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
186                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
187 
188         assertThat(thrown).hasMessageThat().contains("property doesn't have a valid int value.");
189     }
190 
191     @Test
testParsePropertyIdWithStringValue()192     public void testParsePropertyIdWithStringValue() throws Exception {
193         String jsonString = "{\"properties\": "
194                 + "[{\"property\": \"VehicleProperty::INFO_FUEL_CAPACITY\"}]}";
195         File tempFile = createTempFileWithContent(jsonString);
196 
197         int propId = mFakeVhalConfigParser.parseJsonConfig(tempFile)
198                 .get(VehicleProperty.INFO_FUEL_CAPACITY).getConfig().prop;
199 
200         assertThat(propId).isEqualTo(VehicleProperty.INFO_FUEL_CAPACITY);
201     }
202 
203     @Test
testParsePropertyIdWithEmptyStringValue()204     public void testParsePropertyIdWithEmptyStringValue() throws Exception {
205         String jsonString = "{\"properties\": " + "[{\"property\": \"\"}]}";
206         File tempFile = createTempFileWithContent(jsonString);
207 
208         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
209                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
210 
211         assertThat(thrown).hasMessageThat().contains("must in the form of "
212                 + "<EnumClassName>::<ConstantName>.");
213     }
214 
215     @Test
testParsePropertyIdWithIntStringValue()216     public void testParsePropertyIdWithIntStringValue() throws Exception {
217         String jsonString = "{\"properties\": " + "[{\"property\": \"1234\"}]}";
218         File tempFile = createTempFileWithContent(jsonString);
219 
220         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
221                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
222 
223         assertThat(thrown).hasMessageThat().contains("must in the form of "
224                 + "<EnumClassName>::<ConstantName>.");
225     }
226 
227     @Test
testParsePropertyIdWithWrongStringFormat()228     public void testParsePropertyIdWithWrongStringFormat() throws Exception {
229         String jsonString = "{\"properties\": "
230                 + "[{\"property\": \"VehicleProperty:INFO_FUEL_CAPACITY\"}]}";
231         File tempFile = createTempFileWithContent(jsonString);
232 
233         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
234                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
235 
236         assertThat(thrown).hasMessageThat().contains("must in the form of "
237                 + "<EnumClassName>::<ConstantName>.");
238     }
239 
240     @Test
testParsePropertyIdEnumClassNameNotExist()241     public void testParsePropertyIdEnumClassNameNotExist() throws Exception {
242         String jsonString = "{\"properties\": "
243                 + "[{\"property\": \"NotExistEnumClass::INFO_FUEL_CAPACITY\"}]}";
244         File tempFile = createTempFileWithContent(jsonString);
245 
246         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
247                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
248 
249         assertThat(thrown).hasMessageThat().contains("is not a valid class name.");
250     }
251 
252     @Test
testParsePropertyIdEnumClassFieldNameNotExist()253     public void testParsePropertyIdEnumClassFieldNameNotExist() throws Exception {
254         String jsonString = "{\"properties\": "
255                 + "[{\"property\": \"VehicleProperty::NOT_EXIST\"}]}";
256         File tempFile = createTempFileWithContent(jsonString);
257 
258         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
259                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
260 
261         assertThat(thrown).hasMessageThat().contains("VehicleProperty doesn't have a constant field"
262                 + " with name NOT_EXIST");
263     }
264 
265     @Test
testParsePropertyIdEnumClassFieldTypeIsNotInt()266     public void testParsePropertyIdEnumClassFieldTypeIsNotInt() throws Exception {
267         String jsonString = "{\"properties\": "
268                 + "[{\"property\": \"IVehicle::INVALID_MEMORY_ID\"}]}";
269         File tempFile = createTempFileWithContent(jsonString);
270 
271         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
272                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
273 
274         assertThat(thrown).hasMessageThat().contains("Failed to get int value of interface "
275                 + "android.hardware.automotive.vehicle.IVehicle.INVALID_MEMORY_ID");
276     }
277 
278     @Test
testParsePropertyIdFromConstantsMap()279     public void testParsePropertyIdFromConstantsMap() throws Exception {
280         String jsonString = "{\"properties\": [{\"property\": \"Constants::DOOR_1_LEFT\","
281                 + "\"access\": \"VehiclePropertyAccess::READ_WRITE\","
282                 + "\"changeMode\": \"VehiclePropertyChangeMode::STATIC\"}]}";
283         File tempFile = createTempFileWithContent(jsonString);
284 
285         int propId = mFakeVhalConfigParser.parseJsonConfig(tempFile).get(DOOR_1_LEFT).getConfig()
286                 .prop;
287 
288         assertThat(propId).isEqualTo(VehicleAreaDoor.ROW_1_LEFT);
289     }
290 
291     @Test
testParsePropertyIdFromConstantsMapWithWrongConstantsName()292     public void testParsePropertyIdFromConstantsMapWithWrongConstantsName() throws Exception {
293         String jsonString = "{\"properties\": [{\"property\": \"Constants::ROW_1_LEFT\"}]}";
294         File tempFile = createTempFileWithContent(jsonString);
295 
296         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
297                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
298 
299         assertThat(thrown).hasMessageThat().contains("ROW_1_LEFT is not a valid constant name.");
300     }
301 
302     @Test
testParseStringValueIsEmpty()303     public void testParseStringValueIsEmpty() throws Exception {
304         String jsonString = "{\"properties\": [{\"property\": 123, \"configString\": \"\"}]}";
305         File tempFile = createTempFileWithContent(jsonString);
306 
307         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
308                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
309 
310         assertThat(thrown).hasMessageThat().contains(
311                 "configString doesn't have a valid string value.");
312     }
313 
314     @Test
testParseFloatValueIsEmptyString()315     public void testParseFloatValueIsEmptyString() throws Exception {
316         String jsonString = "{\"properties\": [{\"property\": 123, \"minSampleRate\": \"\"}]}";
317         File tempFile = createTempFileWithContent(jsonString);
318 
319         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
320                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
321 
322         assertThat(thrown).hasMessageThat().contains(" must in the form of "
323                 + "<EnumClassName>::<ConstantName>.");
324     }
325 
326     @Test
testParseFloatValueIsString()327     public void testParseFloatValueIsString() throws Exception {
328         String jsonString = "{\"properties\": [{\"property\": 123, "
329                 + "\"access\": \"VehiclePropertyAccess::READ_WRITE\","
330                 + "\"changeMode\": \"VehiclePropertyChangeMode::STATIC\","
331                 + "\"minSampleRate\": \"VehicleUnit::FAHRENHEIT\"}]}";
332         File tempFile = createTempFileWithContent(jsonString);
333 
334         float minSampleRate = mFakeVhalConfigParser.parseJsonConfig(tempFile).get(123).getConfig()
335                 .minSampleRate;
336 
337         assertThat(minSampleRate).isEqualTo(49f);
338     }
339 
340     @Test
testParseFloatValueIsNull()341     public void testParseFloatValueIsNull() throws Exception {
342         String jsonString = "{\"properties\": [{\"property\": 123, \"minSampleRate\": null}]}";
343         File tempFile = createTempFileWithContent(jsonString);
344 
345         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
346                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
347 
348         assertThat(thrown).hasMessageThat().contains("minSampleRate doesn't have a valid float "
349                 + "value.");
350     }
351 
352     @Test
testParseFloatValueIsInt()353     public void testParseFloatValueIsInt() throws Exception {
354         String jsonString = "{\"properties\": [{\"property\": 123,"
355                 + "\"access\": \"VehiclePropertyAccess::READ_WRITE\","
356                 + "\"changeMode\": \"VehiclePropertyChangeMode::STATIC\","
357                 + "\"minSampleRate\": 456}]}";
358         File tempFile = createTempFileWithContent(jsonString);
359 
360         float minSampleRate = mFakeVhalConfigParser.parseJsonConfig(tempFile).get(123).getConfig()
361                 .minSampleRate;
362 
363         assertThat(minSampleRate).isEqualTo(456f);
364     }
365 
366     @Test
testParseAccessFieldOverride()367     public void testParseAccessFieldOverride() throws Exception {
368         String jsonString = "{\"properties\": [{\"property\": \"VehicleProperty::INFO_VIN\", "
369                 + "\"access\": \"VehiclePropertyAccess::READ_WRITE\"}]}";
370         File tempFile = createTempFileWithContent(jsonString);
371 
372         int access = mFakeVhalConfigParser.parseJsonConfig(tempFile).get(VehicleProperty.INFO_VIN)
373                 .getConfig().access;
374 
375         assertThat(access).isEqualTo(VehiclePropertyAccess.READ_WRITE);
376         assertThat(access).isNotEqualTo(AccessForVehicleProperty.values
377                 .get(VehicleProperty.INFO_VIN));
378     }
379 
380     @Test
testParseAccessFieldNotSpecifiedDefaultAccessValueExist()381     public void testParseAccessFieldNotSpecifiedDefaultAccessValueExist() throws Exception {
382         String jsonString = "{\"properties\": [{\"property\": \"VehicleProperty::INFO_VIN\"}]}";
383         File tempFile = createTempFileWithContent(jsonString);
384 
385         int access = mFakeVhalConfigParser.parseJsonConfig(tempFile).get(VehicleProperty.INFO_VIN)
386                 .getConfig().access;
387 
388         assertThat(access).isEqualTo(AccessForVehicleProperty.values.get(VehicleProperty.INFO_VIN));
389     }
390 
391     @Test
testParseAccessFieldNotSpecifiedDefaultAccessValueNotExist()392     public void testParseAccessFieldNotSpecifiedDefaultAccessValueNotExist() throws Exception {
393         String jsonString = "{\"properties\": [{\"property\": 123,"
394                 + "\"changeMode\": \"VehiclePropertyChangeMode::STATIC\"}]}";
395         File tempFile = createTempFileWithContent(jsonString);
396 
397         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
398                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
399 
400         assertThat(thrown).hasMessageThat().contains("Access field is not set for this property");
401     }
402 
403     @Test
testParseChangeModeFieldOverride()404     public void testParseChangeModeFieldOverride() throws Exception {
405         String jsonString = "{\"properties\": [{\"property\": "
406                 + "\"VehicleProperty::PERF_VEHICLE_SPEED_DISPLAY\", "
407                 + "\"changeMode\": \"VehiclePropertyChangeMode::ON_CHANGE\"}]}";
408         File tempFile = createTempFileWithContent(jsonString);
409 
410         int changeMode = mFakeVhalConfigParser.parseJsonConfig(tempFile)
411                 .get(VehicleProperty.PERF_VEHICLE_SPEED_DISPLAY).getConfig().changeMode;
412 
413         assertThat(changeMode).isEqualTo(VehiclePropertyChangeMode.ON_CHANGE);
414         assertThat(changeMode).isNotEqualTo(ChangeModeForVehicleProperty.values
415                 .get(VehicleProperty.PERF_VEHICLE_SPEED_DISPLAY));
416     }
417 
418     @Test
testParseChangeModeFieldNotSpecifiedDefaultChangeModeValueExist()419     public void testParseChangeModeFieldNotSpecifiedDefaultChangeModeValueExist() throws Exception {
420         String jsonString = "{\"properties\": [{\"property\": "
421                 + "\"VehicleProperty::PERF_VEHICLE_SPEED_DISPLAY\"}]}";
422         File tempFile = createTempFileWithContent(jsonString);
423 
424         int changeMode = mFakeVhalConfigParser.parseJsonConfig(tempFile)
425                 .get(VehicleProperty.PERF_VEHICLE_SPEED_DISPLAY).getConfig().changeMode;
426 
427         assertThat(changeMode).isEqualTo(ChangeModeForVehicleProperty.values
428                 .get(VehicleProperty.PERF_VEHICLE_SPEED_DISPLAY));
429     }
430 
431     @Test
testParseChangeModeFieldNotSpecifiedDefaultChangeModeValueNotExist()432     public void testParseChangeModeFieldNotSpecifiedDefaultChangeModeValueNotExist()
433             throws Exception {
434         String jsonString = "{\"properties\": [{\"property\": 123,"
435                 + "\"access\": \"VehiclePropertyAccess::READ\"}]}";
436         File tempFile = createTempFileWithContent(jsonString);
437 
438         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
439                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
440 
441         assertThat(thrown).hasMessageThat().contains("ChangeMode field is not set for this "
442                 + "property");
443     }
444 
445     @Test
testParseConfigArrayValueIsNotArray()446     public void testParseConfigArrayValueIsNotArray() throws Exception {
447         String jsonString = "{\"properties\": [{\"property\": 286261504, \"configArray\": 123}]}";
448         File tempFile = createTempFileWithContent(jsonString);
449 
450         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
451                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
452 
453         assertThat(thrown).hasMessageThat().contains("configArray doesn't have a valid JSONArray "
454                 + "value.");
455     }
456 
457     @Test
testParseConfigArrayValueWithNullElement()458     public void testParseConfigArrayValueWithNullElement() throws Exception {
459         String jsonString = "{\"properties\": [{\"property\": 286261504, \"configArray\": "
460                 + "[123, null]}]}";
461         File tempFile = createTempFileWithContent(jsonString);
462 
463         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
464                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
465 
466         assertThat(thrown).hasMessageThat().contains("configArray doesn't have a valid int value "
467                 + "at index 1");
468     }
469 
470     @Test
testParseDefaultValueIsNull()471     public void testParseDefaultValueIsNull() throws Exception {
472         String jsonString = "{\"properties\": [{\"property\": 286261504, \"defaultValue\": null}]}";
473         File tempFile = createTempFileWithContent(jsonString);
474 
475         assertThrows(IllegalArgumentException.class, () ->
476                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
477     }
478 
479     @Test
testParseDefaultValueIsEmpty()480     public void testParseDefaultValueIsEmpty() throws Exception {
481         String jsonString = "{\"properties\": [{\"property\": 286261504, \"defaultValue\": {}}]}";
482         File tempFile = createTempFileWithContent(jsonString);
483 
484         ConfigDeclaration configDeclaration = mFakeVhalConfigParser.parseJsonConfig(tempFile)
485                 .get(286261504);
486 
487         assertThat(configDeclaration.getInitialValue()).isEqualTo(null);
488     }
489 
490     @Test
testParseDefaultValueIntValuesIsNull()491     public void testParseDefaultValueIntValuesIsNull() throws Exception {
492         String jsonString = "{\"properties\": [{\"property\": 286261504, \"defaultValue\": "
493                 + "{\"int32Values\": null}}]}";
494         File tempFile = createTempFileWithContent(jsonString);
495 
496         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
497                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
498 
499         assertThat(thrown).hasMessageThat().contains(
500                 "int32Values doesn't have a valid JSONArray value");
501     }
502 
503     @Test
testParseDefaultValueParseLongValues()504     public void testParseDefaultValueParseLongValues() throws Exception {
505         String jsonString = "{\"properties\": [{\"property\": 286261504, \"defaultValue\": "
506                 + "{\"int64Values\": [0, 100000, 200000]}}]}";
507         File tempFile = createTempFileWithContent(jsonString);
508 
509         long[] longValues = mFakeVhalConfigParser.parseJsonConfig(tempFile).get(286261504)
510                 .getInitialValue().int64Values;
511         long[] expectLongValues = {0, 100000, 200000};
512         assertThat(longValues).isEqualTo(expectLongValues);
513     }
514 
515     @Test
testParseDefaultValueFloat()516     public void testParseDefaultValueFloat() throws Exception {
517         String jsonString = "{\"properties\": [{\"property\": 286261504, \"defaultValue\": "
518                 + "{\"floatValues\": [2.3, \"VehicleUnit::FAHRENHEIT\"]}}]}";
519         File tempFile = createTempFileWithContent(jsonString);
520 
521         RawPropValues rawPropValues = mFakeVhalConfigParser.parseJsonConfig(tempFile).get(286261504)
522                 .getInitialValue();
523         RawPropValues expectRawPropertyValues = new RawPropValues();
524         expectRawPropertyValues.floatValues = new float[]{2.3f, 49.0f};
525         assertThat(rawPropValues).isEqualTo(expectRawPropertyValues);
526     }
527 
528     @Test
testParseDefaultValueIntValuesString()529     public void testParseDefaultValueIntValuesString() throws Exception {
530         String jsonString = "{\"properties\": [{\"property\": 286261504, \"defaultValue\": "
531                 + "{\"int32Values\": [\"VehicleSeatOccupancyState::VACANT\"]}}]}";
532         File tempFile = createTempFileWithContent(jsonString);
533         RawPropValues expectRawPropertyValues = new RawPropValues();
534         expectRawPropertyValues.int32Values = new int[]{VehicleSeatOccupancyState.VACANT};
535 
536         RawPropValues rawPropValues = mFakeVhalConfigParser.parseJsonConfig(tempFile).get(286261504)
537                 .getInitialValue();
538 
539         assertThat(rawPropValues).isEqualTo(expectRawPropertyValues);
540 
541     }
542 
543     @Test
testParseAreaConfigValueIsNotArray()544     public void testParseAreaConfigValueIsNotArray() throws Exception {
545         String jsonString = "{\"properties\": [{\"property\": 286261504, \"areas\": {}}]}";
546         File tempFile = createTempFileWithContent(jsonString);
547 
548         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
549                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
550 
551         assertThat(thrown).hasMessageThat().contains("areas doesn't have a valid JSONArray value.");
552     }
553 
554     @Test
testParseAreaConfigValueWithNullElement()555     public void testParseAreaConfigValueWithNullElement() throws Exception {
556         String jsonString = "{\"properties\": [{\"property\": 286261504, \"areas\": [null]}]}";
557         File tempFile = createTempFileWithContent(jsonString);
558 
559         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
560                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
561 
562         assertThat(thrown).hasMessageThat().contains("Unable to get a JSONObject element for areas "
563                 + "at index 0");
564     }
565 
566     @Test
testParseAreaConfigValueWithEmptyElement()567     public void testParseAreaConfigValueWithEmptyElement() throws Exception {
568         String jsonString = "{\"properties\": [{\"property\": 286261504, \"areas\": [{}]}]}";
569         File tempFile = createTempFileWithContent(jsonString);
570 
571         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
572                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
573 
574         assertThat(thrown).hasMessageThat().contains("is empty");
575     }
576 
577     @Test
testParseAreaConfigValueElementHasNoAreaId()578     public void testParseAreaConfigValueElementHasNoAreaId() throws Exception {
579         String jsonString = "{\"properties\": [{\"property\": 286261504, \"areas\": "
580                 + "[{\"minInt32Value\": 0}]}]}";
581         File tempFile = createTempFileWithContent(jsonString);
582 
583         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
584                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
585 
586         assertThat(thrown).hasMessageThat().contains("doesn't have areaId. AreaId is required.");
587     }
588 
589     @Test
testParseAreaConfigValueHasNoAccessLevel()590     public void testParseAreaConfigValueHasNoAccessLevel() throws Exception {
591         String jsonString = "{\"properties\": [{\"property\": 286261504, \"areas\": "
592                 + "[{\"areaId\": 1, \"minInt32Value\": 0, \"maxInt32Value\": 10, "
593                 + "\"defaultValue\": {\"int32Values\": [0]}}]}]}";
594         File tempFile = createTempFileWithContent(jsonString);
595         VehiclePropConfig vehiclePropConfig = new VehiclePropConfig();
596         vehiclePropConfig.prop = 286261504;
597         vehiclePropConfig.access = AccessForVehicleProperty.values.get(286261504);
598         VehicleAreaConfig vehicleAreaConfig = new VehicleAreaConfig();
599         vehicleAreaConfig.access = AccessForVehicleProperty.values.get(286261504);
600         vehicleAreaConfig.areaId = 1;
601         vehicleAreaConfig.minInt32Value = 0;
602         vehicleAreaConfig.maxInt32Value = 10;
603         vehiclePropConfig.areaConfigs = new VehicleAreaConfig[]{vehicleAreaConfig};
604         RawPropValues areaRawPropValues = new RawPropValues();
605         areaRawPropValues.int32Values = new int[]{0};
606         SparseArray<RawPropValues> areaValuesByAreaId = new SparseArray<>();
607         areaValuesByAreaId.put(vehicleAreaConfig.areaId, areaRawPropValues);
608         ConfigDeclaration expectConfigDeclaration = new ConfigDeclaration(vehiclePropConfig,
609                 null, areaValuesByAreaId);
610 
611         ConfigDeclaration configDeclaration = mFakeVhalConfigParser.parseJsonConfig(tempFile)
612                 .get(286261504);
613 
614         assertThat(configDeclaration).isEqualTo(expectConfigDeclaration);
615     }
616 
617     @Test
testParseAreaConfigValueHasAccessLevel()618     public void testParseAreaConfigValueHasAccessLevel() throws Exception {
619         String jsonString = "{\"properties\": [{\"property\": 286261504, \"areas\": "
620                 + "[{\"access\": 2, \"areaId\": 1, \"minInt32Value\": 0, \"maxInt32Value\": 10, "
621                 + "\"defaultValue\": {\"int32Values\": [0]}}]}]}";
622         File tempFile = createTempFileWithContent(jsonString);
623         VehiclePropConfig vehiclePropConfig = new VehiclePropConfig();
624         vehiclePropConfig.prop = 286261504;
625         vehiclePropConfig.access = AccessForVehicleProperty.values.get(286261504);
626         VehicleAreaConfig vehicleAreaConfig = new VehicleAreaConfig();
627         vehicleAreaConfig.access = 2;
628         vehicleAreaConfig.areaId = 1;
629         vehicleAreaConfig.minInt32Value = 0;
630         vehicleAreaConfig.maxInt32Value = 10;
631         vehiclePropConfig.areaConfigs = new VehicleAreaConfig[]{vehicleAreaConfig};
632         RawPropValues areaRawPropValues = new RawPropValues();
633         areaRawPropValues.int32Values = new int[]{0};
634         SparseArray<RawPropValues> areaValuesByAreaId = new SparseArray<>();
635         areaValuesByAreaId.put(vehicleAreaConfig.areaId, areaRawPropValues);
636         ConfigDeclaration expectConfigDeclaration = new ConfigDeclaration(vehiclePropConfig,
637                 null, areaValuesByAreaId);
638 
639         ConfigDeclaration configDeclaration = mFakeVhalConfigParser.parseJsonConfig(tempFile)
640                 .get(286261504);
641 
642         assertThat(configDeclaration).isEqualTo(expectConfigDeclaration);
643     }
644 
645     @Test
testParseAreaConfig_PropertyConfigHasAccessLevel()646     public void testParseAreaConfig_PropertyConfigHasAccessLevel() throws Exception {
647         String jsonString = "{\"properties\": [{\"property\": 286261504, \"areas\": "
648                 + "[{\"areaId\": 1, \"minInt32Value\": 0, \"maxInt32Value\": 10, "
649                 + "\"defaultValue\": {\"int32Values\": [0]}}], \"access\": 2}]}";
650         File tempFile = createTempFileWithContent(jsonString);
651         VehiclePropConfig vehiclePropConfig = new VehiclePropConfig();
652         vehiclePropConfig.prop = 286261504;
653         vehiclePropConfig.access = 2;
654         VehicleAreaConfig vehicleAreaConfig = new VehicleAreaConfig();
655         vehicleAreaConfig.access = 2;
656         vehicleAreaConfig.areaId = 1;
657         vehicleAreaConfig.minInt32Value = 0;
658         vehicleAreaConfig.maxInt32Value = 10;
659         vehiclePropConfig.areaConfigs = new VehicleAreaConfig[]{vehicleAreaConfig};
660         RawPropValues areaRawPropValues = new RawPropValues();
661         areaRawPropValues.int32Values = new int[]{0};
662         SparseArray<RawPropValues> areaValuesByAreaId = new SparseArray<>();
663         areaValuesByAreaId.put(vehicleAreaConfig.areaId, areaRawPropValues);
664         ConfigDeclaration expectConfigDeclaration = new ConfigDeclaration(vehiclePropConfig,
665                 null, areaValuesByAreaId);
666 
667         ConfigDeclaration configDeclaration = mFakeVhalConfigParser.parseJsonConfig(tempFile)
668                 .get(286261504);
669 
670         assertThat(configDeclaration).isEqualTo(expectConfigDeclaration);
671     }
672 
673     @Test
testParseAreaConfig_PropertyAndAreaConfigHasAccessLevel()674     public void testParseAreaConfig_PropertyAndAreaConfigHasAccessLevel() throws Exception {
675         String jsonString = "{\"properties\": [{\"property\": 286261504, \"areas\": "
676                 + "[{\"access\": 3, \"areaId\": 1, \"minInt32Value\": 0, \"maxInt32Value\": 10, "
677                 + "\"defaultValue\": {\"int32Values\": [0]}}], \"access\": 2}]}";
678         File tempFile = createTempFileWithContent(jsonString);
679         VehiclePropConfig vehiclePropConfig = new VehiclePropConfig();
680         vehiclePropConfig.prop = 286261504;
681         vehiclePropConfig.access = 2;
682         VehicleAreaConfig vehicleAreaConfig = new VehicleAreaConfig();
683         vehicleAreaConfig.access = 3;
684         vehicleAreaConfig.areaId = 1;
685         vehicleAreaConfig.minInt32Value = 0;
686         vehicleAreaConfig.maxInt32Value = 10;
687         vehiclePropConfig.areaConfigs = new VehicleAreaConfig[]{vehicleAreaConfig};
688         RawPropValues areaRawPropValues = new RawPropValues();
689         areaRawPropValues.int32Values = new int[]{0};
690         SparseArray<RawPropValues> areaValuesByAreaId = new SparseArray<>();
691         areaValuesByAreaId.put(vehicleAreaConfig.areaId, areaRawPropValues);
692         ConfigDeclaration expectConfigDeclaration = new ConfigDeclaration(vehiclePropConfig,
693                 null, areaValuesByAreaId);
694 
695         ConfigDeclaration configDeclaration = mFakeVhalConfigParser.parseJsonConfig(tempFile)
696                 .get(286261504);
697 
698         assertThat(configDeclaration).isEqualTo(expectConfigDeclaration);
699     }
700 
701     @Test
testParseAreaConfigWithNoValue()702     public void testParseAreaConfigWithNoValue() throws Exception {
703         String jsonString = "{\"properties\": [{\"property\": 286261504, \"areas\": "
704                 + "[{\"areaId\": 1, \"minInt32Value\": 0, \"maxInt32Value\": 10, "
705                 + "\"defaultValue\": {\"int32Values\": [0]}}, {\"areaId\": 2}]}]}";
706         File tempFile = createTempFileWithContent(jsonString);
707 
708         ConfigDeclaration configDeclaration = mFakeVhalConfigParser.parseJsonConfig(tempFile)
709                 .get(286261504);
710 
711         assertThat(configDeclaration.getInitialAreaValuesByAreaId().size()).isEqualTo(1);
712         assertThat(configDeclaration.getInitialAreaValuesByAreaId().get(1).int32Values[0])
713                 .isEqualTo(0);
714     }
715 
716     @Test
testParseJsonConfig()717     public void testParseJsonConfig() throws Exception {
718         // Create a JSON config object with all field values set.
719         String jsonString = "{\"properties\": [{"
720                 + "             \"property\": "
721                 + "               \"VehicleProperty::WHEEL_TICK\","
722                 + "               \"defaultValue\": {"
723                 + "                 \"int64Values\": [0, 100000, 200000, 300000, 400000]"
724                 + "               },"
725                 + "               \"areas\": [{"
726                 + "                 \"defaultValue\": {"
727                 + "                   \"int32Values\": [\"VehicleSeatOccupancyState::VACANT\"],"
728                 + "                   \"floatValues\": [15000.0],"
729                 + "                   \"stringValue\": \"Toy Vehicle\""
730                 + "                 },"
731                 + "                 \"minInt32Value\": 0,"
732                 + "                 \"maxInt32Value\": 10,"
733                 + "                 \"access\": \"VehiclePropertyAccess::READ_WRITE\","
734                 + "                 \"areaId\": \"Constants::SEAT_1_LEFT\""
735                 + "               },{"
736                 + "                 \"defaultValue\": {"
737                 + "                   \"int32Values\": [0]"
738                 + "                 },"
739                 + "                   \"areaId\": \"Constants::SEAT_1_RIGHT\""
740                 + "               }],"
741                 + "            \"configArray\": [15, 50000, 50000, 50000, 50000],"
742                 + "            \"configString\": \"configString\","
743                 + "            \"maxSampleRate\": 10.0,"
744                 + "            \"minSampleRate\": 1.0,"
745                 + "            \"access\": \"VehiclePropertyAccess::READ\","
746                 + "            \"changeMode\": \"VehiclePropertyChangeMode::STATIC\""
747                 + "        }]}";
748         File tempFile = createTempFileWithContent(jsonString);
749         // Create prop config object
750         VehiclePropConfig vehiclePropConfig = new VehiclePropConfig();
751         vehiclePropConfig.prop = VehicleProperty.WHEEL_TICK;
752         vehiclePropConfig.access = VehiclePropertyAccess.READ;
753         // Create area config object
754         VehicleAreaConfig vehicleAreaConfig1 = new VehicleAreaConfig();
755         vehicleAreaConfig1.areaId = VehicleAreaSeat.ROW_1_LEFT;
756         vehicleAreaConfig1.minInt32Value = 0;
757         vehicleAreaConfig1.maxInt32Value = 10;
758         vehicleAreaConfig1.access = VehiclePropertyAccess.READ_WRITE;
759         VehicleAreaConfig vehicleAreaConfig2 = new VehicleAreaConfig();
760         vehicleAreaConfig2.areaId = VehicleAreaSeat.ROW_1_RIGHT;
761         vehicleAreaConfig2.access = VehiclePropertyAccess.READ;
762         vehiclePropConfig.areaConfigs = new VehicleAreaConfig[]{vehicleAreaConfig1,
763                 vehicleAreaConfig2};
764         vehiclePropConfig.configString = "configString";
765         vehiclePropConfig.configArray = new int[]{15, 50000, 50000, 50000, 50000};
766         vehiclePropConfig.minSampleRate = 1.0f;
767         vehiclePropConfig.maxSampleRate = 10.0f;
768         vehiclePropConfig.changeMode = VehiclePropertyChangeMode.STATIC;
769         // Create default prop value object.
770         RawPropValues defaultRawPropValues = new RawPropValues();
771         defaultRawPropValues.int64Values = new long[]{0, 100000, 200000, 300000, 400000};
772         // Create area prop value objects.
773         RawPropValues areaRawPropValues1 = new RawPropValues();
774         areaRawPropValues1.int32Values = new int[]{VehicleSeatOccupancyState.VACANT};
775         areaRawPropValues1.floatValues = new float[]{15000.0f};
776         areaRawPropValues1.stringValue = "Toy Vehicle";
777         RawPropValues areaRawPropValues2 = new RawPropValues();
778         areaRawPropValues2.int32Values = new int[]{0};
779         // Create map from areaId to areaValue.
780         SparseArray<RawPropValues> areaValuesByAreaId = new SparseArray<>();
781         areaValuesByAreaId.put(vehicleAreaConfig1.areaId, areaRawPropValues1);
782         areaValuesByAreaId.put(vehicleAreaConfig2.areaId, areaRawPropValues2);
783         // Create expected ConfigDeclaration object.
784         ConfigDeclaration expectConfigDeclaration = new ConfigDeclaration(vehiclePropConfig,
785                 defaultRawPropValues, areaValuesByAreaId);
786 
787         ConfigDeclaration configDeclaration = mFakeVhalConfigParser.parseJsonConfig(tempFile)
788                 .get(VehicleProperty.WHEEL_TICK);
789 
790         assertThat(expectConfigDeclaration.getConfig().changeMode).isEqualTo(0);
791         assertThat(expectConfigDeclaration).isEqualTo(configDeclaration);
792         assertThat(expectConfigDeclaration.hashCode()).isEqualTo(configDeclaration.hashCode());
793         assertThat(expectConfigDeclaration.toString()).isEqualTo(configDeclaration.toString());
794     }
795 
796     @Test
testParseJsonConfigWithMultiErrors()797     public void testParseJsonConfigWithMultiErrors() throws Exception {
798         String jsonString = "{\"properties\": ["
799                 + "              {"
800                 + "                  \"property\": 1234"
801                 + "              },"
802                 + "              null,"
803                 + "              {},"
804                 + "              {"
805                 + "                  \"defaultValue\": {"
806                 + "                      \"int64Values\": [0, 100000, 200000, 300000, 400000]"
807                 + "                  }"
808                 + "              },"
809                 + "              {"
810                 + "                  \"property\": \"NotExistEnumClass::INFO_FUEL_CAPACITY\""
811                 + "              },"
812                 + "              {"
813                 + "                  \"property\": 286261504,"
814                 + "                  \"configArray\": 123"
815                 + "              },"
816                 + "              {"
817                 + "                  \"property\": 286261504,"
818                 + "                  \"defaultValue\": {"
819                 + "                      \"int32Values\": null"
820                 + "                  }"
821                 + "              },"
822                 + "              {"
823                 + "                  \"property\": 286261504,"
824                 + "                  \"areas\": [{"
825                 + "                      \"minInt32Value\": 0"
826                 + "                  }]"
827                 + "              }"
828                 + "          ]}";
829         File tempFile = createTempFileWithContent(jsonString);
830 
831         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
832                 mFakeVhalConfigParser.parseJsonConfig(tempFile));
833 
834         assertThat(thrown).hasMessageThat().contains("Access field is not set for this property:");
835         assertThat(thrown).hasMessageThat().contains("ChangeMode field is not set for this "
836                 + "property:");
837         assertThat(thrown).hasMessageThat().contains("Unable to parse property config at index 0");
838         assertThat(thrown).hasMessageThat().contains("properties array has an invalid JSON element "
839                 + "at index 1");
840         assertThat(thrown).hasMessageThat().contains("is empty");
841         assertThat(thrown).hasMessageThat().contains("at index 2");
842         assertThat(thrown).hasMessageThat().contains("PropId is required");
843         assertThat(thrown).hasMessageThat().contains("at index 3");
844         assertThat(thrown).hasMessageThat().contains("is not a valid class name.");
845         assertThat(thrown).hasMessageThat().contains("at index 4");
846         assertThat(thrown).hasMessageThat().contains(
847                 "configArray doesn't have a valid JSONArray value");
848         assertThat(thrown).hasMessageThat().contains("at index 5");
849         assertThat(thrown).hasMessageThat().contains(
850                 "int32Values doesn't have a valid JSONArray value");
851         assertThat(thrown).hasMessageThat().contains("at index 6");
852         assertThat(thrown).hasMessageThat().contains("doesn't have areaId. AreaId is required.");
853         assertThat(thrown).hasMessageThat().contains("at index 7");
854     }
855 
856     @Test
testParseDefaultConfigFile()857     public void testParseDefaultConfigFile() throws Exception {
858         InputStream inputStream = this.getClass().getClassLoader()
859                 .getResourceAsStream("DefaultProperties.json");
860 
861         SparseArray<ConfigDeclaration> result = mFakeVhalConfigParser.parseJsonConfig(inputStream);
862 
863         assertThat(result.get(VehicleProperty.INFO_FUEL_CAPACITY).getConfig().prop)
864                 .isEqualTo(VehicleProperty.INFO_FUEL_CAPACITY);
865         assertThat(result.get(VehicleProperty.INFO_FUEL_CAPACITY).getInitialValue().floatValues[0])
866                 .isEqualTo(15000.0f);
867         assertThat(result.get(VehicleProperty.PERF_VEHICLE_SPEED).getConfig().maxSampleRate)
868                 .isEqualTo(10.0f);
869         assertThat(result.get(VehicleProperty.VEHICLE_SPEED_DISPLAY_UNITS).getConfig().configArray)
870                 .isEqualTo(new int[]{VehicleUnit.METER_PER_SEC, VehicleUnit.MILES_PER_HOUR,
871                         VehicleUnit.KILOMETERS_PER_HOUR});
872         assertThat(result.get(VehicleProperty.SEAT_OCCUPANCY).getInitialValue().int32Values[0])
873                 .isEqualTo(VehicleSeatOccupancyState.VACANT);
874         assertThat(result.get(VehicleProperty.TIRE_PRESSURE).getConfig().areaConfigs[0].areaId)
875                 .isEqualTo(WHEEL_FRONT_LEFT);
876     }
877 
878     @Test
testParseJsonConfig_areaAccessInheritFromGlobal()879     public void testParseJsonConfig_areaAccessInheritFromGlobal() throws Exception {
880         // Create a JSON config object with all field values set.
881         String jsonString = "{\"properties\": [{"
882                 + "             \"property\": 12345,"
883                 + "               \"areas\": [{"
884                 + "                 \"minInt32Value\": 0,"
885                 + "                 \"maxInt32Value\": 10,"
886                 + "                 \"areaId\": 54321"
887                 + "               }],"
888                 + "            \"access\": \"VehiclePropertyAccess::READ\","
889                 + "            \"changeMode\": \"VehiclePropertyChangeMode::STATIC\""
890                 + "        }]}";
891         File tempFile = createTempFileWithContent(jsonString);
892 
893         ConfigDeclaration configDeclaration = mFakeVhalConfigParser.parseJsonConfig(tempFile)
894                 .get(12345);
895 
896         assertThat(configDeclaration.getConfig().areaConfigs[0].access).isEqualTo(
897                 VehiclePropertyAccess.READ);
898     }
899 
900     @Test
testParseJsonConfig_areaAccessOverwritesGlobal()901     public void testParseJsonConfig_areaAccessOverwritesGlobal() throws Exception {
902         // Create a JSON config object with all field values set.
903         String jsonString = "{\"properties\": [{"
904                 + "             \"property\": 12345,"
905                 + "               \"areas\": [{"
906                 + "                 \"minInt32Value\": 0,"
907                 + "                 \"maxInt32Value\": 10,"
908                 + "                 \"access\": \"VehiclePropertyAccess::READ_WRITE\","
909                 + "                 \"areaId\": 54321"
910                 + "               }],"
911                 + "            \"access\": \"VehiclePropertyAccess::READ\","
912                 + "            \"changeMode\": \"VehiclePropertyChangeMode::STATIC\""
913                 + "        }]}";
914         File tempFile = createTempFileWithContent(jsonString);
915 
916         ConfigDeclaration configDeclaration = mFakeVhalConfigParser.parseJsonConfig(tempFile)
917                 .get(12345);
918 
919         assertThat(configDeclaration.getConfig().areaConfigs[0].access).isEqualTo(
920                 VehiclePropertyAccess.READ_WRITE);
921     }
922 
923     @Test
testParseJsonConfig_areaAccessUseDefault()924     public void testParseJsonConfig_areaAccessUseDefault() throws Exception {
925         // Create a JSON config object with all field values set.
926         String jsonString = "{\"properties\": [{"
927                 + "             \"property\": \"VehicleProperty::WHEEL_TICK\","
928                 + "               \"areas\": [{"
929                 + "                 \"minInt32Value\": 0,"
930                 + "                 \"maxInt32Value\": 10,"
931                 + "                 \"areaId\": 54321"
932                 + "               }],"
933                 + "            \"changeMode\": \"VehiclePropertyChangeMode::STATIC\""
934                 + "        }]}";
935         File tempFile = createTempFileWithContent(jsonString);
936 
937         ConfigDeclaration configDeclaration = mFakeVhalConfigParser.parseJsonConfig(tempFile)
938                 .get(VehicleProperty.WHEEL_TICK);
939 
940         // WHEEL_TICK default access is READ.
941         assertThat(configDeclaration.getConfig().areaConfigs[0].access).isEqualTo(
942                 VehiclePropertyAccess.READ);
943     }
944 
createTempFileWithContent(String fileContent)945     private File createTempFileWithContent(String fileContent) throws Exception {
946         File tempFile = File.createTempFile("test", ".json");
947         tempFile.deleteOnExit();
948         FileOutputStream os = new FileOutputStream(tempFile);
949         os.write(fileContent.getBytes());
950         return tempFile;
951     }
952 }