blob: 61f66f3aed9c8df33d570867d58863ec478005d0 [file] [log] [blame]
Pavel Maltseva067be42016-03-21 10:17:25 -07001/*
2 * Copyright (C) 2016 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.vehiclenetwork.haltest;
18
19import static java.lang.Integer.toHexString;
20import static junit.framework.Assert.assertTrue;
21
22import android.util.Log;
23
24import com.android.car.vehiclenetwork.VehicleNetwork.VehicleNetworkListener;
25import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType;
26import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue;
27import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValues;
28import com.android.car.vehiclenetwork.VehicleNetworkProtoUtil;
29
30import java.util.ArrayList;
31import java.util.Arrays;
32import java.util.Collection;
33import java.util.HashSet;
34import java.util.List;
35import java.util.Objects;
36import java.util.Set;
37
38/**
39 * This class must be used in testing environment only. Here's an example of usage:
40 * <ul>
41 * <li>listener.reset();
42 * <li>listener.addExpectedValues(myPropertyId, myZone, 10, 20, 30)
43 * <li>... set values through VehicleNetworkService ...
44 * <li>listener.waitAndVerifyValues()
45 *</ul>
46 *
47 */
48class RecordingVehicleNetworkListener implements VehicleNetworkListener {
49
50 private final static String TAG = VnsHalBaseTestCase.TAG;
51 private final static int EVENTS_WAIT_TIMEOUT_MS = 2000;
52
53 private final Set<NormalizedValue> mExpectedValues = new HashSet<>();
54 // Using Set here instead of List as we probably shouldn't assert the order event was received.
55 private final Set<NormalizedValue> mRecordedEvents = new HashSet<>();
56
57 synchronized void reset() {
58 mExpectedValues.clear();
59 mRecordedEvents.clear();
60 }
61
62 void addExpectedValues(int propertyId, int zone, Object... values) {
63 for (Object value : values) {
64 mExpectedValues.add(NormalizedValue.createFor(propertyId, zone, value));
65 }
66 }
67
68 /**
69 * Waits for events to come for #EVENTS_WAIT_TIMEOUT_MS milliseconds and asserts that recorded
70 * values match with expected.
71 * */
72 synchronized void waitAndVerifyValues() throws InterruptedException {
73 long currentTime = System.currentTimeMillis();
74 long deadline = currentTime + EVENTS_WAIT_TIMEOUT_MS;
75 while (currentTime < deadline && !isExpectedMatchedRecorded()) {
76 wait(deadline - currentTime);
77 currentTime = System.currentTimeMillis();
78 }
79 assertTrue("Expected values: " + Arrays.toString(mExpectedValues.toArray())
80 + " doesn't match recorded: " + Arrays.toString(mRecordedEvents.toArray()),
81 isExpectedMatchedRecorded());
82 }
83
84 private boolean isExpectedMatchedRecorded() {
85 for (NormalizedValue expectedValue : mExpectedValues) {
86 if (!mRecordedEvents.contains(expectedValue)) {
87 return false;
88 }
89 }
90 return true;
91 }
92
93 @Override
94 public void onVehicleNetworkEvents(VehiclePropValues values) {
95 for (VehiclePropValue value : values.getValuesList()) {
96 Log.d(TAG, "onVehicleNetworkEvents, value: "
97 + VehicleNetworkProtoUtil.VehiclePropValueToString(value));
98
99 synchronized (this) {
100 mRecordedEvents.add(NormalizedValue.createFor(value));
101 notifyAll();
102 }
103 }
104 }
105
106 @Override
107 public void onHalError(int errorCode, int property, int operation) {
108 // TODO Auto-generated method stub
109 }
110
111 @Override
112 public void onHalRestart(boolean inMocking) {
113 // TODO Auto-generated method stub
114 }
115
Pavel Maltsevb0324b42016-09-27 21:00:41 -0700116 @Override
117 public void onPropertySet(VehiclePropValue value) {
118 // TODO
119 }
120
Pavel Maltseva067be42016-03-21 10:17:25 -0700121 // To be used to compare expected vs recorded values.
122 private static class NormalizedValue {
123 private final int propertyId;
124 private final int zone;
125 private final List<Object> value;
126
127 static NormalizedValue createFor(VehiclePropValue value) {
128 return new NormalizedValue(value.getProp(), value.getZone(), getObjectValue(value));
129 }
130
131 static NormalizedValue createFor(int propertyId, int zone, Object value) {
132 return new NormalizedValue(propertyId, zone, wrapSingleObjectToList(value));
133 }
134
135 // Do not call this ctor directly, use appropriate factory methods to create an object.
136 private NormalizedValue(int propertyId, int zone, List<Object> value) {
137 this.propertyId = propertyId;
138 this.zone = zone;
139 this.value = value;
140 }
141
142 @Override
143 public boolean equals(Object o) {
144 if (this == o) {
145 return true;
146 }
147 if (o == null || getClass() != o.getClass()) {
148 return false;
149 }
150 NormalizedValue propValue = (NormalizedValue) o;
151 return propertyId == propValue.propertyId &&
152 zone == propValue.zone &&
153 Objects.equals(value, propValue.value);
154 }
155
156 @Override
157 public int hashCode() {
158 return Objects.hash(propertyId, zone, value);
159 }
160
161 @Override
162 public String toString() {
163 return getClass().getSimpleName() + " { "
164 + "prop: 0x" + toHexString(propertyId)
165 + ", zone: 0x" + toHexString(zone)
166 + ", value: " + Arrays.toString(value.toArray())
167 + " }";
168 }
169
170 private static List<Object> wrapSingleObjectToList(Object value) {
171 if (value instanceof Integer
172 || value instanceof Float) {
173 List<Object> list = new ArrayList<>(1);
174 list.add(value);
175 return list;
176 } else if (value instanceof Boolean) {
177 List<Object> list = new ArrayList<>(1);
178 list.add((Boolean)value ? 1 : 0);
179 return list;
180 } else if (value instanceof Collection<?>) {
181 return new ArrayList<>((Collection<?>) value);
182 } else {
183 throw new IllegalArgumentException("Unexpected type: " + value);
184 }
185 }
186
187 // Converts any VehiclePropValue to either ArrayList<Integer> or ArrayList<Float>
188 private static List<Object> getObjectValue(VehiclePropValue val) {
189 switch (val.getValueType()) {
190 case VehicleValueType.VEHICLE_VALUE_TYPE_BOOLEAN:
191 case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_BOOLEAN:
192 case VehicleValueType.VEHICLE_VALUE_TYPE_INT32:
193 case VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC2:
194 case VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC3:
195 case VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC4:
196 case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32:
197 case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2:
198 case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3:
199 case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4:
200 return new ArrayList<>(val.getInt32ValuesList());
201 case VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT:
202 case VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC2:
203 case VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC3:
204 case VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC4:
205 case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT:
206 case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2:
207 case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3:
208 case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4:
209 return new ArrayList<>(val.getFloatValuesList());
210 default:
211 throw new IllegalArgumentException("Unexpected type: " + val.getValueType());
212 }
213 }
214 }
215}