package org.ovirt.engine.api.restapi.test.util;
import static org.mockito.ArgumentMatchers.argThat;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import org.mockito.ArgumentMatcher;
import org.ovirt.engine.core.common.queries.SearchParameters;
public class TestHelper {
public static <T> T eqParams(Class<T> clz, String[] names, Object[] values) {
return argThat(new ParametersEquals<>(clz, names, values));
}
protected static Method getMethod(Class<?> clz, String name) throws NoSuchMethodException {
return clz.getMethod("get" + name);
}
protected static Method getMethod(Class<?> clz, String name, Object value) throws NoSuchMethodException {
Method method = null;
try {
method = getMethod(clz, name);
} catch (NoSuchMethodException nsme) {
if (Boolean.class.equals(value.getClass())) {
method = clz.getMethod("is" + name);
} else {
throw nsme;
}
}
return method;
}
protected static boolean matches(Object lhs, Object rhs) {
boolean matches = true;
if (lhs instanceof List && rhs instanceof Iterable) {
List<?> llhs = (List<?>)lhs;
Iterator<?> irhs = ((Iterable<?>)rhs).iterator();
int count = 0;
while (irhs.hasNext()) {
count++;
matches = llhs.contains(irhs.next());
if (!matches) {
break;
}
}
if (matches) {
matches = count == llhs.size();
}
}
else if (lhs instanceof byte[] && rhs instanceof byte[]) {
byte[] lhsBytes = (byte[]) lhs;
byte[] rhsBytes = (byte[]) rhs;
matches = lhsBytes.length == rhsBytes.length;
if (matches) {
matches = matches && Arrays.equals(lhsBytes, rhsBytes);
}
}
else {
matches = Objects.equals(lhs, rhs);
}
return matches;
}
protected static boolean matches(Class<?> clz, Object instance, String name, Object value) {
try {
if (!topLevel(name)) {
instance = getMethod(clz, superField(name)).invoke(instance);
clz = instance.getClass();
name = subField(name);
}
return matches(value, getMethod(clz, name, value).invoke(instance));
} catch (Exception e) {
return false;
}
}
private static boolean topLevel(String name) {
return !name.contains(".");
}
private static String superField(String name) {
return name.substring(0, name.indexOf("."));
}
private static String subField(String name) {
return name.substring(name.indexOf(".") + 1);
}
/**
* This generic matcher for parameter objects is required because these types
* don't override Object.equals() with a deep comparison
*/
protected static class ParametersEquals<T> implements ArgumentMatcher<T> {
Class<T> clz;
String[] names;
Object[] values;
public ParametersEquals(Class<T> clz, String[] names, Object[] values) {
this.clz = clz;
this.names = names;
this.values = values;
}
@Override
public boolean matches(T actual) {
if (clz.isInstance(actual)) {
for (int i = 0; i < names.length; i++) {
if (!TestHelper.matches(clz, actual, names[i], values[i])) {
return false;
}
}
return true;
}
return false;
}
}
public static SearchParameters eqSearchParams(SearchParameters expected) {
return argThat(new SearchParametersEquals(expected));
}
/**
* This specialized matcher for SearchParameters is required because this
* type doesn't override Object.equals() with a deep comparison
*/
protected static class SearchParametersEquals implements ArgumentMatcher<SearchParameters> {
private SearchParameters expected;
public SearchParametersEquals(SearchParameters expected) {
this.expected = expected;
}
@Override
public boolean matches(SearchParameters actual) {
return expected.getSearchPattern().equals(actual.getSearchPattern())
&& expected.getSearchTypeValue().equals(actual.getSearchTypeValue());
}
}
}