1 package net.avcompris.commons.query.tests;
2
3 import static com.google.common.base.Preconditions.checkArgument;
4 import static com.google.common.base.Preconditions.checkNotNull;
5 import static net.avcompris.commons.query.impl.FieldUtils.extractPropertyName;
6 import static net.avcompris.commons.query.impl.FieldUtils.isBooleanField;
7 import static net.avcompris.commons.query.impl.FilteringsFactory.instantiate;
8 import static org.apache.commons.lang3.StringUtils.capitalize;
9
10 import java.lang.reflect.InvocationHandler;
11 import java.lang.reflect.Method;
12 import java.lang.reflect.Proxy;
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.List;
16 import java.util.stream.Stream;
17
18 import org.junit.jupiter.params.ParameterizedTest;
19 import org.junit.jupiter.params.provider.Arguments;
20 import org.junit.jupiter.params.provider.MethodSource;
21
22 import net.avcompris.commons.query.FilterSyntaxException;
23 import net.avcompris.commons.query.Filtering;
24 import net.avcompris.commons.query.Filterings;
25 import net.avcompris.commons.query.impl.Operation;
26
27 public abstract class AbstractAllFilterByTest<T extends Filtering<U>, U extends Filtering.Field> {
28
29 private final Class<?> dtoClass;
30
31
32
33 private final Filterings<T, U> filterings;
34
35
36
37 protected AbstractAllFilterByTest(final Class<? extends Filterings<T, U>> filteringsClass,
38 final Class<?> dtoClass) {
39
40
41 checkNotNull(filteringsClass, "filteringsClass");
42 this.dtoClass = checkNotNull(dtoClass, "dtoClass");
43
44
45
46
47 filterings = instantiate(filteringsClass);
48
49 checkArgument(dtoClass.isInterface(),
50 "dtoClass should be an interface: %s", dtoClass.getName());
51 }
52
53 @ParameterizedTest(name = "{0}")
54 @MethodSource("testCases")
55 public final void testParse(final String expression, final U field) throws Exception {
56
57 final String s = expression + " " + newValueFor(field);
58
59 parse(s);
60 }
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 @ParameterizedTest(name = "{0}")
89 @MethodSource("testCases")
90 public final void testMatch(final String expression, final U field) throws Exception {
91
92 final T filtering = filterings.parse(expression + " " + newValueFor(field));
93
94
95
96
97
98 final String prefix;
99
100 if (isBooleanField(field)) {
101
102 prefix = "is";
103
104 } else {
105
106 prefix = "get";
107 }
108
109 final String propertyName = extractPropertyName(field);
110
111 final String getterMethodName = prefix + capitalize(propertyName);
112
113 final Object p = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
114 new Class<?>[] { dtoClass }, new InvocationHandler() {
115
116 @Override
117 public Object invoke(final Object proxy, final Method method, final Object[] args)
118 throws Throwable {
119
120 final String expectedMethodName = method.getReturnType().isArray()
121 ? getterMethodName + "s"
122 : getterMethodName;
123
124 if (!expectedMethodName.contentEquals(method.getName())) {
125 throw new IllegalStateException(
126 "method: " + method + ", expectedMethodName: " + expectedMethodName);
127 }
128
129 return randomValueFor(field);
130 }
131 });
132
133 filtering.match(p);
134 }
135
136 protected abstract Object newValueFor(U field);
137
138 protected final Object randomValueFor(final U field) {
139
140 return newValueFor(field);
141 }
142
143 protected final T parse(final String expression) throws FilterSyntaxException {
144
145 return filterings.parse(expression);
146 }
147
148 protected static <U extends Filtering.Field> Stream<Arguments> testCases(final U[] values) throws Exception {
149
150 return parameters(values).stream()
151 .map((args) -> Arguments.of(args[0], args[1]));
152 }
153
154 private static <U extends Filtering.Field> Collection<Object[]> parameters(final U[] values) throws Exception {
155
156 final List<Object[]> parameters = new ArrayList<>();
157
158 for (final U field : values) {
159
160 for (final Operation operation : Operation.getOperations(field)) {
161
162 final String expression = field + " " + operation;
163
164 parameters.add(new Object[] { expression, field });
165 }
166 }
167
168 return parameters;
169 }
170 }