1 /* 2 * Copyright (C) 2020 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 package android.car.test.mocks; 17 18 import static org.mockito.ArgumentMatchers.argThat; 19 20 import android.annotation.Nullable; 21 import android.annotation.UserIdInt; 22 import android.content.pm.UserInfo; 23 import android.hardware.automotive.vehicle.V2_0.VehiclePropValue; 24 import android.os.UserHandle; 25 import android.util.Log; 26 27 import org.mockito.ArgumentMatcher; 28 29 import java.util.Arrays; 30 31 /** 32 * Provides custom mockito matcher for Android / Car objects. 33 * 34 */ 35 public final class CarArgumentMatchers { 36 37 private static final String TAG = CarArgumentMatchers.class.getSimpleName(); 38 39 /** 40 * Matches if a {@link UserInfo} has the given {@code userId}. 41 */ isUserInfo(@serIdInt int userId)42 public static UserInfo isUserInfo(@UserIdInt int userId) { 43 return argThat(new UserInfoMatcher(userId)); 44 } 45 46 /** 47 * Matches if a {@link UserHandle} has the given {@code userId}. 48 */ isUserHandle(@serIdInt int userId)49 public static UserHandle isUserHandle(@UserIdInt int userId) { 50 return argThat(new UserHandleMatcher(userId)); 51 } 52 53 /** 54 * Matches if a {@link VehiclePropValue} has the given {@code prop}. 55 */ isProperty(int prop)56 public static VehiclePropValue isProperty(int prop) { 57 return argThat(new PropertyIdMatcher(prop)); 58 } 59 60 /** 61 * Matches if a {@link VehiclePropValue} has the given {@code prop} and {@code int32} values. 62 */ isPropertyWithValues(int prop, int...values)63 public static VehiclePropValue isPropertyWithValues(int prop, int...values) { 64 return argThat(new PropertyIdMatcher(prop, values)); 65 } 66 67 private static class UserInfoMatcher implements ArgumentMatcher<UserInfo> { 68 69 public final @UserIdInt int userId; 70 UserInfoMatcher(@serIdInt int userId)71 private UserInfoMatcher(@UserIdInt int userId) { 72 this.userId = userId; 73 } 74 75 @Override matches(@ullable UserInfo argument)76 public boolean matches(@Nullable UserInfo argument) { 77 if (argument == null) { 78 Log.w(TAG, "isUserInfo(): null argument"); 79 return false; 80 } 81 if (argument.id != userId) { 82 Log.w(TAG, "isUserInfo(): argument mismatch (expected " + userId 83 + ", got " + argument.id); 84 return false; 85 } 86 return true; 87 } 88 89 @Override toString()90 public String toString() { 91 return "isUserInfo(userId=" + userId + ")"; 92 } 93 } 94 95 private static class UserHandleMatcher implements ArgumentMatcher<UserHandle> { 96 97 public final @UserIdInt int userId; 98 UserHandleMatcher(@serIdInt int userId)99 private UserHandleMatcher(@UserIdInt int userId) { 100 this.userId = userId; 101 } 102 103 @Override matches(UserHandle argument)104 public boolean matches(UserHandle argument) { 105 if (argument == null) { 106 Log.w(TAG, "isUserHandle(): null argument"); 107 return false; 108 } 109 if (argument.getIdentifier() != userId) { 110 Log.w(TAG, "isUserHandle(): argument mismatch (expected " + userId 111 + ", got " + argument.getIdentifier()); 112 return false; 113 } 114 return true; 115 } 116 117 @Override toString()118 public String toString() { 119 return "isUserHandle(userId=" + userId + ")"; 120 } 121 } 122 123 private static class PropertyIdMatcher implements ArgumentMatcher<VehiclePropValue> { 124 125 final int mProp; 126 private final int[] mValues; 127 PropertyIdMatcher(int prop)128 private PropertyIdMatcher(int prop) { 129 this(prop, null); 130 } 131 PropertyIdMatcher(int prop, int[] values)132 private PropertyIdMatcher(int prop, int[] values) { 133 mProp = prop; 134 mValues = values; 135 } 136 137 @Override matches(VehiclePropValue argument)138 public boolean matches(VehiclePropValue argument) { 139 Log.v(TAG, "PropertyIdMatcher: argument=" + argument); 140 if (argument.prop != mProp) { 141 Log.w(TAG, "PropertyIdMatcher: Invalid prop on " + argument); 142 return false; 143 } 144 if (mValues == null) return true; 145 // Make sure values match 146 if (mValues.length != argument.value.int32Values.size()) { 147 Log.w(TAG, "PropertyIdMatcher: number of values (expected " + mValues.length 148 + ") mismatch on " + argument); 149 return false; 150 } 151 152 for (int i = 0; i < mValues.length; i++) { 153 if (mValues[i] != argument.value.int32Values.get(i)) { 154 Log.w(TAG, "PropertyIdMatcher: value mismatch at index " + i + " on " + argument 155 + ": expected " + Arrays.toString(mValues)); 156 return false; 157 } 158 } 159 return true; 160 } 161 162 @Override toString()163 public String toString() { 164 return "prop: " + mProp + " values: " + Arrays.toString(mValues); 165 } 166 } 167 CarArgumentMatchers()168 private CarArgumentMatchers() { 169 throw new UnsupportedOperationException("contains only static methods"); 170 } 171 } 172