ResolvableTypeTests.java 67.9 KB
Newer Older
P
Phillip Webb 已提交
1
/*
2
 * Copyright 2002-2019 the original author or authors.
P
Phillip Webb 已提交
3 4 5 6 7
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
S
Spring Operator 已提交
8
 *      https://www.apache.org/licenses/LICENSE-2.0
P
Phillip Webb 已提交
9 10 11 12 13 14 15 16 17 18
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.core;

P
Phillip Webb 已提交
19 20 21 22
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
P
Phillip Webb 已提交
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.AbstractCollection;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
40
import java.util.Set;
P
Phillip Webb 已提交
41 42
import java.util.SortedSet;
import java.util.TreeSet;
43
import java.util.concurrent.Callable;
P
Phillip Webb 已提交
44

45
import org.assertj.core.api.AbstractAssert;
P
Phillip Webb 已提交
46 47 48 49
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
50
import org.mockito.junit.MockitoJUnitRunner;
J
Juergen Hoeller 已提交
51

P
Phillip Webb 已提交
52
import org.springframework.core.ResolvableType.VariableResolver;
P
Phillip Webb 已提交
53 54
import org.springframework.util.MultiValueMap;

55
import static org.assertj.core.api.Assertions.assertThat;
56 57
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.ArgumentMatchers.any;
P
Phillip Webb 已提交
58 59 60 61
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
P
Phillip Webb 已提交
62 63

/**
64 65
 * Tests for {@link ResolvableType}.
 *
P
Phillip Webb 已提交
66
 * @author Phillip Webb
67
 * @author Juergen Hoeller
S
sdeleuze 已提交
68
 * @author Sebastien Deleuze
P
Phillip Webb 已提交
69 70 71 72 73 74 75 76 77 78 79 80
 */
@SuppressWarnings("rawtypes")
@RunWith(MockitoJUnitRunner.class)
public class ResolvableTypeTests {

	@Captor
	private ArgumentCaptor<TypeVariable<?>> typeVariableCaptor;


	@Test
	public void noneReturnValues() throws Exception {
		ResolvableType none = ResolvableType.NONE;
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
		assertThat(none.as(Object.class)).isEqualTo(ResolvableType.NONE);
		assertThat(none.asCollection()).isEqualTo(ResolvableType.NONE);
		assertThat(none.asMap()).isEqualTo(ResolvableType.NONE);
		assertThat(none.getComponentType()).isEqualTo(ResolvableType.NONE);
		assertThat(none.getGeneric(0)).isEqualTo(ResolvableType.NONE);
		assertThat(none.getGenerics().length).isEqualTo(0);
		assertThat(none.getInterfaces().length).isEqualTo(0);
		assertThat(none.getSuperType()).isEqualTo(ResolvableType.NONE);
		assertThat(none.getType()).isEqualTo(ResolvableType.EmptyType.INSTANCE);
		assertThat(none.hasGenerics()).isEqualTo(false);
		assertThat(none.isArray()).isEqualTo(false);
		assertThat(none.resolve()).isNull();
		assertThat(none.resolve(String.class)).isEqualTo(String.class);
		assertThat(none.resolveGeneric(0)).isNull();
		assertThat(none.resolveGenerics().length).isEqualTo(0);
		assertThat(none.toString()).isEqualTo("?");
		assertThat(none.hasUnresolvableGenerics()).isEqualTo(false);
		assertThat(none.isAssignableFrom(ResolvableType.forClass(Object.class))).isEqualTo(false);
P
Phillip Webb 已提交
99 100 101 102 103
	}

	@Test
	public void forClass() throws Exception {
		ResolvableType type = ResolvableType.forClass(ExtendsList.class);
104 105
		assertThat(type.getType()).isEqualTo(ExtendsList.class);
		assertThat(type.getRawClass()).isEqualTo(ExtendsList.class);
106 107
		assertThat(type.isAssignableFrom(ExtendsList.class)).isTrue();
		assertThat(type.isAssignableFrom(ArrayList.class)).isFalse();
P
Phillip Webb 已提交
108 109 110
	}

	@Test
111 112
	public void forClassWithNull() throws Exception {
		ResolvableType type = ResolvableType.forClass(null);
113 114
		assertThat(type.getType()).isEqualTo(Object.class);
		assertThat(type.getRawClass()).isEqualTo(Object.class);
115 116
		assertThat(type.isAssignableFrom(Object.class)).isTrue();
		assertThat(type.isAssignableFrom(String.class)).isTrue();
117 118 119 120 121
	}

	@Test
	public void forRawClass() throws Exception {
		ResolvableType type = ResolvableType.forRawClass(ExtendsList.class);
122 123
		assertThat(type.getType()).isEqualTo(ExtendsList.class);
		assertThat(type.getRawClass()).isEqualTo(ExtendsList.class);
124 125
		assertThat(type.isAssignableFrom(ExtendsList.class)).isTrue();
		assertThat(type.isAssignableFrom(ArrayList.class)).isFalse();
126 127 128 129 130
	}

	@Test
	public void forRawClassWithNull() throws Exception {
		ResolvableType type = ResolvableType.forRawClass(null);
131 132
		assertThat(type.getType()).isEqualTo(Object.class);
		assertThat(type.getRawClass()).isEqualTo(Object.class);
133 134
		assertThat(type.isAssignableFrom(Object.class)).isTrue();
		assertThat(type.isAssignableFrom(String.class)).isTrue();
P
Phillip Webb 已提交
135 136
	}

137 138 139 140 141 142 143 144 145 146 147 148
	@Test
	public void forRawClassAssignableFromTypeVariable() { // gh-23321
		ResolvableType typeVariable = ResolvableType.forClass(ExtendsList.class).as(List.class).getGeneric();
		ResolvableType raw = ResolvableType.forRawClass(CharSequence.class);
		assertThat(raw.resolve()).isEqualTo(CharSequence.class);
		assertThat(typeVariable.resolve()).isEqualTo(CharSequence.class);
		assertThat(raw.resolve().isAssignableFrom(typeVariable.resolve())).isTrue();
		assertThat(typeVariable.resolve().isAssignableFrom(raw.resolve())).isTrue();
		assertThat(raw.isAssignableFrom(typeVariable)).isTrue();
		assertThat(typeVariable.isAssignableFrom(raw)).isTrue();
	}

S
Stephane Nicoll 已提交
149
	@Test
J
Juergen Hoeller 已提交
150
	public void forInstanceMustNotBeNull() throws Exception {
151 152 153
		assertThatIllegalArgumentException().isThrownBy(() ->
				ResolvableType.forInstance(null))
			.withMessageContaining("Instance must not be null");
S
Stephane Nicoll 已提交
154 155 156
	}

	@Test
J
Juergen Hoeller 已提交
157
	public void forInstanceNoProvider() throws Exception {
S
Stephane Nicoll 已提交
158
		ResolvableType type = ResolvableType.forInstance(new Object());
159 160
		assertThat(type.getType()).isEqualTo(Object.class);
		assertThat(type.resolve()).isEqualTo(Object.class);
S
Stephane Nicoll 已提交
161 162 163
	}

	@Test
J
Juergen Hoeller 已提交
164
	public void forInstanceProvider() throws Exception {
165
		ResolvableType type = ResolvableType.forInstance(new MyGenericInterfaceType<>(String.class));
166 167
		assertThat(type.getRawClass()).isEqualTo(MyGenericInterfaceType.class);
		assertThat(type.getGeneric().resolve()).isEqualTo(String.class);
S
Stephane Nicoll 已提交
168 169 170
	}

	@Test
J
Juergen Hoeller 已提交
171
	public void forInstanceProviderNull() throws Exception {
S
Stephane Nicoll 已提交
172
		ResolvableType type = ResolvableType.forInstance(new MyGenericInterfaceType<String>(null));
173 174
		assertThat(type.getType()).isEqualTo(MyGenericInterfaceType.class);
		assertThat(type.resolve()).isEqualTo(MyGenericInterfaceType.class);
S
Stephane Nicoll 已提交
175 176
	}

P
Phillip Webb 已提交
177 178 179 180
	@Test
	public void forField() throws Exception {
		Field field = Fields.class.getField("charSequenceList");
		ResolvableType type = ResolvableType.forField(field);
181
		assertThat(type.getType()).isEqualTo(field.getGenericType());
P
Phillip Webb 已提交
182 183 184 185 186 187
	}

	@Test
	public void forPrivateField() throws Exception {
		Field field = Fields.class.getDeclaredField("privateField");
		ResolvableType type = ResolvableType.forField(field);
188 189 190
		assertThat(type.getType()).isEqualTo(field.getGenericType());
		assertThat(type.resolve()).isEqualTo(List.class);
		assertThat(type.getSource()).isSameAs(field);
191 192 193

		Field field2 = Fields.class.getDeclaredField("otherPrivateField");
		ResolvableType type2 = ResolvableType.forField(field2);
194 195 196
		assertThat(type2.getType()).isEqualTo(field2.getGenericType());
		assertThat(type2.resolve()).isEqualTo(List.class);
		assertThat(type2.getSource()).isSameAs(field2);
197

198 199
		assertThat(type2).isEqualTo(type);
		assertThat(type2.hashCode()).isEqualTo(type.hashCode());
P
Phillip Webb 已提交
200 201 202 203
	}

	@Test
	public void forFieldMustNotBeNull() throws Exception {
204 205 206
		assertThatIllegalArgumentException().isThrownBy(() ->
				ResolvableType.forField(null))
			.withMessageContaining("Field must not be null");
P
Phillip Webb 已提交
207 208 209 210 211 212
	}

	@Test
	public void forConstructorParameter() throws Exception {
		Constructor<Constructors> constructor = Constructors.class.getConstructor(List.class);
		ResolvableType type = ResolvableType.forConstructorParameter(constructor, 0);
213
		assertThat(type.getType()).isEqualTo(constructor.getGenericParameterTypes()[0]);
P
Phillip Webb 已提交
214 215 216 217
	}

	@Test
	public void forConstructorParameterMustNotBeNull() throws Exception {
218 219 220
		assertThatIllegalArgumentException().isThrownBy(() ->
				ResolvableType.forConstructorParameter(null, 0))
			.withMessageContaining("Constructor must not be null");
P
Phillip Webb 已提交
221 222 223 224 225 226
	}

	@Test
	public void forMethodParameterByIndex() throws Exception {
		Method method = Methods.class.getMethod("charSequenceParameter", List.class);
		ResolvableType type = ResolvableType.forMethodParameter(method, 0);
227
		assertThat(type.getType()).isEqualTo(method.getGenericParameterTypes()[0]);
P
Phillip Webb 已提交
228 229 230 231
	}

	@Test
	public void forMethodParameterByIndexMustNotBeNull() throws Exception {
232 233 234
		assertThatIllegalArgumentException().isThrownBy(() ->
				ResolvableType.forMethodParameter(null, 0))
			.withMessageContaining("Method must not be null");
P
Phillip Webb 已提交
235 236 237 238 239
	}

	@Test
	public void forMethodParameter() throws Exception {
		Method method = Methods.class.getMethod("charSequenceParameter", List.class);
240
		MethodParameter methodParameter = MethodParameter.forExecutable(method, 0);
P
Phillip Webb 已提交
241
		ResolvableType type = ResolvableType.forMethodParameter(methodParameter);
242
		assertThat(type.getType()).isEqualTo(method.getGenericParameterTypes()[0]);
P
Phillip Webb 已提交
243 244 245 246 247
	}

	@Test
	public void forMethodParameterWithNesting() throws Exception {
		Method method = Methods.class.getMethod("nested", Map.class);
248
		MethodParameter methodParameter = MethodParameter.forExecutable(method, 0);
P
Phillip Webb 已提交
249 250
		methodParameter.increaseNestingLevel();
		ResolvableType type = ResolvableType.forMethodParameter(methodParameter);
251 252 253
		assertThat(type.resolve()).isEqualTo(Map.class);
		assertThat(type.getGeneric(0).resolve()).isEqualTo(Byte.class);
		assertThat(type.getGeneric(1).resolve()).isEqualTo(Long.class);
P
Phillip Webb 已提交
254 255 256 257 258
	}

	@Test
	public void forMethodParameterWithNestingAndLevels() throws Exception {
		Method method = Methods.class.getMethod("nested", Map.class);
259
		MethodParameter methodParameter = MethodParameter.forExecutable(method, 0);
P
Phillip Webb 已提交
260 261 262
		methodParameter.increaseNestingLevel();
		methodParameter.setTypeIndexForCurrentLevel(0);
		ResolvableType type = ResolvableType.forMethodParameter(methodParameter);
263 264 265
		assertThat(type.resolve()).isEqualTo(Map.class);
		assertThat(type.getGeneric(0).resolve()).isEqualTo(String.class);
		assertThat(type.getGeneric(1).resolve()).isEqualTo(Integer.class);
P
Phillip Webb 已提交
266 267 268 269
	}

	@Test
	public void forMethodParameterMustNotBeNull() throws Exception {
270 271 272
		assertThatIllegalArgumentException().isThrownBy(() ->
				ResolvableType.forMethodParameter(null))
			.withMessageContaining("MethodParameter must not be null");
P
Phillip Webb 已提交
273 274
	}

S
sdeleuze 已提交
275 276 277 278 279
	@Test  // SPR-16210
	public void forMethodParameterWithSameSignatureAndGenerics() throws Exception {
		Method method = Methods.class.getMethod("list1");
		MethodParameter methodParameter = MethodParameter.forExecutable(method, -1);
		ResolvableType type = ResolvableType.forMethodParameter(methodParameter);
280
		assertThat(((MethodParameter)type.getSource()).getMethod()).isEqualTo(method);
S
sdeleuze 已提交
281 282 283 284

		method = Methods.class.getMethod("list2");
		methodParameter = MethodParameter.forExecutable(method, -1);
		type = ResolvableType.forMethodParameter(methodParameter);
285
		assertThat(((MethodParameter)type.getSource()).getMethod()).isEqualTo(method);
S
sdeleuze 已提交
286 287
	}

P
Phillip Webb 已提交
288 289 290
	@Test
	public void forMethodReturn() throws Exception {
		Method method = Methods.class.getMethod("charSequenceReturn");
J
Juergen Hoeller 已提交
291
		ResolvableType type = ResolvableType.forMethodReturnType(method);
292
		assertThat(type.getType()).isEqualTo(method.getGenericReturnType());
P
Phillip Webb 已提交
293 294 295 296
	}

	@Test
	public void forMethodReturnMustNotBeNull() throws Exception {
297 298 299
		assertThatIllegalArgumentException().isThrownBy(() ->
				ResolvableType.forMethodReturnType(null))
			.withMessageContaining("Method must not be null");
P
Phillip Webb 已提交
300 301 302 303 304
	}

	@Test
	public void classType() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("classType"));
305
		assertThat(type.getType().getClass()).isEqualTo(Class.class);
P
Phillip Webb 已提交
306 307 308 309 310
	}

	@Test
	public void paramaterizedType() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("parameterizedType"));
311
		assertThat(type.getType()).isInstanceOf(ParameterizedType.class);
P
Phillip Webb 已提交
312 313 314 315 316
	}

	@Test
	public void arrayClassType() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("arrayClassType"));
317 318
		assertThat(type.getType()).isInstanceOf(Class.class);
		assertThat(((Class) type.getType()).isArray()).isEqualTo(true);
P
Phillip Webb 已提交
319 320 321 322 323
	}

	@Test
	public void genericArrayType() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("genericArrayType"));
324
		assertThat(type.getType()).isInstanceOf(GenericArrayType.class);
P
Phillip Webb 已提交
325 326 327 328 329
	}

	@Test
	public void wildcardType() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("wildcardType"));
330 331
		assertThat(type.getType()).isInstanceOf(ParameterizedType.class);
		assertThat(type.getGeneric().getType()).isInstanceOf(WildcardType.class);
P
Phillip Webb 已提交
332 333 334 335 336
	}

	@Test
	public void typeVariableType() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("typeVariableType"));
337
		assertThat(type.getType()).isInstanceOf(TypeVariable.class);
P
Phillip Webb 已提交
338 339 340 341 342 343
	}

	@Test
	public void getComponentTypeForClassArray() throws Exception {
		Field field = Fields.class.getField("arrayClassType");
		ResolvableType type = ResolvableType.forField(field);
344 345 346
		assertThat(type.isArray()).isEqualTo(true);
		assertThat(type.getComponentType().getType())
			.isEqualTo(((Class) field.getGenericType()).getComponentType());
P
Phillip Webb 已提交
347 348 349 350 351
	}

	@Test
	public void getComponentTypeForGenericArrayType() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("genericArrayType"));
352 353 354
		assertThat(type.isArray()).isEqualTo(true);
		assertThat(type.getComponentType().getType()).isEqualTo(
				((GenericArrayType) type.getType()).getGenericComponentType());
P
Phillip Webb 已提交
355 356 357 358 359
	}

	@Test
	public void getComponentTypeForVariableThatResolvesToGenericArray() throws Exception {
		ResolvableType type = ResolvableType.forClass(ListOfGenericArray.class).asCollection().getGeneric();
360 361 362 363
		assertThat(type.isArray()).isEqualTo(true);
		assertThat(type.getType()).isInstanceOf(TypeVariable.class);
		assertThat(type.getComponentType().getType().toString()).isEqualTo(
				"java.util.List<java.lang.String>");
P
Phillip Webb 已提交
364 365 366 367 368
	}

	@Test
	public void getComponentTypeForNonArray() throws Exception {
		ResolvableType type = ResolvableType.forClass(String.class);
369 370
		assertThat(type.isArray()).isEqualTo(false);
		assertThat(type.getComponentType()).isEqualTo(ResolvableType.NONE);
P
Phillip Webb 已提交
371 372 373 374 375
	}

	@Test
	public void asCollection() throws Exception {
		ResolvableType type = ResolvableType.forClass(ExtendsList.class).asCollection();
376 377
		assertThat(type.resolve()).isEqualTo(Collection.class);
		assertThat(type.resolveGeneric()).isEqualTo(CharSequence.class);
P
Phillip Webb 已提交
378 379 380 381 382
	}

	@Test
	public void asMap() throws Exception {
		ResolvableType type = ResolvableType.forClass(ExtendsMap.class).asMap();
383 384 385
		assertThat(type.resolve()).isEqualTo(Map.class);
		assertThat(type.resolveGeneric(0)).isEqualTo(String.class);
		assertThat(type.resolveGeneric(1)).isEqualTo(Integer.class);
P
Phillip Webb 已提交
386 387 388 389 390
	}

	@Test
	public void asFromInterface() throws Exception {
		ResolvableType type = ResolvableType.forClass(ExtendsList.class).as(List.class);
391
		assertThat(type.getType().toString()).isEqualTo("java.util.List<E>");
P
Phillip Webb 已提交
392 393 394 395 396
	}

	@Test
	public void asFromInheritedInterface() throws Exception {
		ResolvableType type = ResolvableType.forClass(ExtendsList.class).as(Collection.class);
397
		assertThat(type.getType().toString()).isEqualTo("java.util.Collection<E>");
P
Phillip Webb 已提交
398 399 400 401 402
	}

	@Test
	public void asFromSuperType() throws Exception {
		ResolvableType type = ResolvableType.forClass(ExtendsList.class).as(ArrayList.class);
403
		assertThat(type.getType().toString()).isEqualTo("java.util.ArrayList<java.lang.CharSequence>");
P
Phillip Webb 已提交
404 405 406 407 408
	}

	@Test
	public void asFromInheritedSuperType() throws Exception {
		ResolvableType type = ResolvableType.forClass(ExtendsList.class).as(List.class);
409
		assertThat(type.getType().toString()).isEqualTo("java.util.List<E>");
P
Phillip Webb 已提交
410 411 412 413 414
	}

	@Test
	public void asNotFound() throws Exception {
		ResolvableType type = ResolvableType.forClass(ExtendsList.class).as(Map.class);
415
		assertThat(type).isSameAs(ResolvableType.NONE);
P
Phillip Webb 已提交
416 417 418 419 420
	}

	@Test
	public void asSelf() throws Exception {
		ResolvableType type = ResolvableType.forClass(ExtendsList.class);
421
		assertThat(type.as(ExtendsList.class)).isEqualTo(type);
P
Phillip Webb 已提交
422 423 424 425 426
	}

	@Test
	public void getSuperType() throws Exception {
		ResolvableType type = ResolvableType.forClass(ExtendsList.class).getSuperType();
427
		assertThat(type.resolve()).isEqualTo(ArrayList.class);
P
Phillip Webb 已提交
428
		type = type.getSuperType();
429
		assertThat(type.resolve()).isEqualTo(AbstractList.class);
P
Phillip Webb 已提交
430
		type = type.getSuperType();
431
		assertThat(type.resolve()).isEqualTo(AbstractCollection.class);
P
Phillip Webb 已提交
432
		type = type.getSuperType();
433
		assertThat(type.resolve()).isEqualTo(Object.class);
P
Phillip Webb 已提交
434 435 436 437 438
	}

	@Test
	public void getInterfaces() throws Exception {
		ResolvableType type = ResolvableType.forClass(ExtendsList.class);
439
		assertThat(type.getInterfaces().length).isEqualTo(0);
440
		SortedSet<String> interfaces = new TreeSet<>();
P
Phillip Webb 已提交
441 442 443
		for (ResolvableType interfaceType : type.getSuperType().getInterfaces()) {
			interfaces.add(interfaceType.toString());
		}
444
		assertThat(interfaces.toString()).isEqualTo(
445
				"["
P
Phillip Webb 已提交
446 447 448 449
				+ "java.io.Serializable, "
				+ "java.lang.Cloneable, "
				+ "java.util.List<java.lang.CharSequence>, "
				+ "java.util.RandomAccess"
450
				+ "]");
P
Phillip Webb 已提交
451 452 453 454
	}

	@Test
	public void noSuperType() throws Exception {
455 456
		assertThat(ResolvableType.forClass(Object.class).getSuperType())
				.isEqualTo(ResolvableType.NONE);
P
Phillip Webb 已提交
457 458 459 460
	}

	@Test
	public void noInterfaces() throws Exception {
461
		assertThat(ResolvableType.forClass(Object.class).getInterfaces()).isEmpty();
P
Phillip Webb 已提交
462 463 464 465 466 467
	}

	@Test
	public void nested() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("nested"));
		type = type.getNested(2);
468 469 470
		assertThat(type.resolve()).isEqualTo(Map.class);
		assertThat(type.getGeneric(0).resolve()).isEqualTo(Byte.class);
		assertThat(type.getGeneric(1).resolve()).isEqualTo(Long.class);
P
Phillip Webb 已提交
471 472 473 474 475 476
	}

	@Test
	public void nestedWithIndexes() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("nested"));
		type = type.getNested(2, Collections.singletonMap(2, 0));
477 478 479
		assertThat(type.resolve()).isEqualTo(Map.class);
		assertThat(type.getGeneric(0).resolve()).isEqualTo(String.class);
		assertThat(type.getGeneric(1).resolve()).isEqualTo(Integer.class);
P
Phillip Webb 已提交
480 481 482 483 484 485
	}

	@Test
	public void nestedWithArray() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("genericArrayType"));
		type = type.getNested(2);
486 487
		assertThat(type.resolve()).isEqualTo(List.class);
		assertThat(type.resolveGeneric()).isEqualTo(String.class);
P
Phillip Webb 已提交
488 489 490 491 492
	}

	@Test
	public void getGeneric() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("stringList"));
493
		assertThat(type.getGeneric().getType()).isEqualTo(String.class);
P
Phillip Webb 已提交
494 495 496 497 498
	}

	@Test
	public void getGenericByIndex() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("stringIntegerMultiValueMap"));
499 500
		assertThat(type.getGeneric(0).getType()).isEqualTo(String.class);
		assertThat(type.getGeneric(1).getType()).isEqualTo(Integer.class);
P
Phillip Webb 已提交
501 502 503 504 505
	}

	@Test
	public void getGenericOfGeneric() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("stringListList"));
506 507
		assertThat(type.getGeneric().getType().toString()).isEqualTo("java.util.List<java.lang.String>");
		assertThat(type.getGeneric().getGeneric().getType()).isEqualTo(String.class);
P
Phillip Webb 已提交
508 509
	}

P
Phillip Webb 已提交
510 511 512
	@Test
	public void genericOfGenericWithAs() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("stringListList")).asCollection();
513 514
		assertThat(type.toString()).isEqualTo("java.util.Collection<java.util.List<java.lang.String>>");
		assertThat(type.getGeneric().asCollection().toString()).isEqualTo("java.util.Collection<java.lang.String>");
P
Phillip Webb 已提交
515 516
	}

P
Phillip Webb 已提交
517 518 519
	@Test
	public void getGenericOfGenericByIndexes() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("stringListList"));
520
		assertThat(type.getGeneric(0, 0).getType()).isEqualTo(String.class);
P
Phillip Webb 已提交
521 522 523 524 525
	}

	@Test
	public void getGenericOutOfBounds() throws Exception {
		ResolvableType type = ResolvableType.forClass(List.class, ExtendsList.class);
526 527 528
		assertThat(type.getGeneric(0)).isNotEqualTo(ResolvableType.NONE);
		assertThat(type.getGeneric(1)).isEqualTo(ResolvableType.NONE);
		assertThat(type.getGeneric(0, 1)).isEqualTo(ResolvableType.NONE);
P
Phillip Webb 已提交
529 530 531 532 533
	}

	@Test
	public void hasGenerics() throws Exception {
		ResolvableType type = ResolvableType.forClass(ExtendsList.class);
534 535
		assertThat(type.hasGenerics()).isEqualTo(false);
		assertThat(type.asCollection().hasGenerics()).isEqualTo(true);
P
Phillip Webb 已提交
536 537 538
	}

	@Test
P
Phillip Webb 已提交
539
	public void getGenericsFromParameterizedType() throws Exception {
P
Phillip Webb 已提交
540 541
		ResolvableType type = ResolvableType.forClass(List.class, ExtendsList.class);
		ResolvableType[] generics = type.getGenerics();
542 543
		assertThat(generics.length).isEqualTo(1);
		assertThat(generics[0].resolve()).isEqualTo(CharSequence.class);
P
Phillip Webb 已提交
544 545
	}

P
Phillip Webb 已提交
546 547 548 549
	@Test
	public void getGenericsFromClass() throws Exception {
		ResolvableType type = ResolvableType.forClass(List.class);
		ResolvableType[] generics = type.getGenerics();
550 551
		assertThat(generics.length).isEqualTo(1);
		assertThat(generics[0].getType().toString()).isEqualTo("E");
P
Phillip Webb 已提交
552 553
	}

P
Phillip Webb 已提交
554 555 556 557
	@Test
	public void noGetGenerics() throws Exception {
		ResolvableType type = ResolvableType.forClass(ExtendsList.class);
		ResolvableType[] generics = type.getGenerics();
558
		assertThat(generics.length).isEqualTo(0);
P
Phillip Webb 已提交
559 560 561 562 563 564
	}

	@Test
	public void getResolvedGenerics() throws Exception {
		ResolvableType type = ResolvableType.forClass(List.class, ExtendsList.class);
		Class<?>[] generics = type.resolveGenerics();
565 566
		assertThat(generics.length).isEqualTo(1);
		assertThat(generics[0]).isEqualTo(CharSequence.class);
P
Phillip Webb 已提交
567 568 569 570 571
	}

	@Test
	public void resolveClassType() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("classType"));
572
		assertThat(type.resolve()).isEqualTo(List.class);
P
Phillip Webb 已提交
573 574 575 576 577
	}

	@Test
	public void resolveParameterizedType() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("parameterizedType"));
578
		assertThat(type.resolve()).isEqualTo(List.class);
P
Phillip Webb 已提交
579 580 581 582 583
	}

	@Test
	public void resolveArrayClassType() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("arrayClassType"));
584
		assertThat(type.resolve()).isEqualTo(List[].class);
P
Phillip Webb 已提交
585 586 587 588 589
	}

	@Test
	public void resolveGenericArrayType() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("genericArrayType"));
590 591 592
		assertThat(type.resolve()).isEqualTo(List[].class);
		assertThat(type.getComponentType().resolve()).isEqualTo(List.class);
		assertThat(type.getComponentType().getGeneric().resolve()).isEqualTo(String.class);
P
Phillip Webb 已提交
593 594 595 596 597
	}

	@Test
	public void resolveGenericMultiArrayType() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("genericMultiArrayType"));
598 599
		assertThat(type.resolve()).isEqualTo(List[][][].class);
		assertThat(type.getComponentType().resolve()).isEqualTo(List[][].class);
P
Phillip Webb 已提交
600 601 602 603 604 605
	}

	@Test
	public void resolveGenericArrayFromGeneric() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("stringArrayList"));
		ResolvableType generic = type.asCollection().getGeneric();
606 607 608
		assertThat(generic.getType().toString()).isEqualTo("E");
		assertThat(generic.isArray()).isEqualTo(true);
		assertThat(generic.resolve()).isEqualTo(String[].class);
P
Phillip Webb 已提交
609 610
	}

611 612 613
	@Test
	public void resolveVariableGenericArray() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("variableTypeGenericArray"), TypedFields.class);
614 615 616
		assertThat(type.getType().toString()).isEqualTo("T[]");
		assertThat(type.isArray()).isEqualTo(true);
		assertThat(type.resolve()).isEqualTo(String[].class);
617 618 619 620 621
	}

	@Test
	public void resolveVariableGenericArrayUnknown() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("variableTypeGenericArray"));
622 623 624
		assertThat(type.getType().toString()).isEqualTo("T[]");
		assertThat(type.isArray()).isEqualTo(true);
		assertThat(type.resolve()).isNull();
625 626 627 628 629
	}

	@Test
	public void resolveVariableGenericArrayUnknownWithFallback() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("variableTypeGenericArray"));
630 631 632
		assertThat(type.getType().toString()).isEqualTo("T[]");
		assertThat(type.isArray()).isEqualTo(true);
		assertThat(type.toClass()).isEqualTo(Object.class);
633 634
	}

P
Phillip Webb 已提交
635 636 637
	@Test
	public void resolveWildcardTypeUpperBounds() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("wildcardType"));
638
		assertThat(type.getGeneric().resolve()).isEqualTo(Number.class);
P
Phillip Webb 已提交
639 640 641 642 643
	}

	@Test
	public void resolveWildcardLowerBounds() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("wildcardSuperType"));
644
		assertThat(type.getGeneric().resolve()).isEqualTo(Number.class);
P
Phillip Webb 已提交
645 646 647 648 649
	}

	@Test
	public void resolveVariableFromFieldType() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("stringList"));
650 651
		assertThat(type.resolve()).isEqualTo(List.class);
		assertThat(type.getGeneric().resolve()).isEqualTo(String.class);
P
Phillip Webb 已提交
652 653 654 655 656
	}

	@Test
	public void resolveVariableFromFieldTypeUnknown() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("parameterizedType"));
657 658
		assertThat(type.resolve()).isEqualTo(List.class);
		assertThat(type.getGeneric().resolve()).isNull();
P
Phillip Webb 已提交
659 660 661 662 663 664
	}

	@Test
	public void resolveVariableFromInheritedField() throws Exception {
		ResolvableType type = ResolvableType.forField(
				Fields.class.getField("stringIntegerMultiValueMap")).as(Map.class);
665 666 667
		assertThat(type.getGeneric(0).resolve()).isEqualTo(String.class);
		assertThat(type.getGeneric(1).resolve()).isEqualTo(List.class);
		assertThat(type.getGeneric(1, 0).resolve()).isEqualTo(Integer.class);
P
Phillip Webb 已提交
668 669 670 671 672 673
	}

	@Test
	public void resolveVariableFromInheritedFieldSwitched() throws Exception {
		ResolvableType type = ResolvableType.forField(
				Fields.class.getField("stringIntegerMultiValueMapSwitched")).as(Map.class);
674 675 676
		assertThat(type.getGeneric(0).resolve()).isEqualTo(String.class);
		assertThat(type.getGeneric(1).resolve()).isEqualTo(List.class);
		assertThat(type.getGeneric(1, 0).resolve()).isEqualTo(Integer.class);
P
Phillip Webb 已提交
677 678 679 680 681 682
	}

	@Test
	public void doesResolveFromOuterOwner() throws Exception {
		ResolvableType type = ResolvableType.forField(
				Fields.class.getField("listOfListOfUnknown")).as(Collection.class);
683 684
		assertThat(type.getGeneric(0).resolve()).isEqualTo(List.class);
		assertThat(type.getGeneric(0).as(Collection.class).getGeneric(0).as(Collection.class).resolve()).isNull();
P
Phillip Webb 已提交
685 686 687 688
	}

	@Test
	public void resolveBoundedTypeVariableResult() throws Exception {
J
Juergen Hoeller 已提交
689
		ResolvableType type = ResolvableType.forMethodReturnType(Methods.class.getMethod("boundedTypeVaraibleResult"));
690
		assertThat(type.resolve()).isEqualTo(CharSequence.class);
P
Phillip Webb 已提交
691 692 693 694
	}

	@Test
	public void resolveVariableNotFound() throws Exception {
J
Juergen Hoeller 已提交
695
		ResolvableType type = ResolvableType.forMethodReturnType(Methods.class.getMethod("typedReturn"));
696
		assertThat(type.resolve()).isNull();
P
Phillip Webb 已提交
697 698 699 700
	}

	@Test
	public void resolveTypeVaraibleFromMethodReturn() throws Exception {
J
Juergen Hoeller 已提交
701
		ResolvableType type = ResolvableType.forMethodReturnType(Methods.class.getMethod("typedReturn"));
702
		assertThat(type.resolve()).isNull();
P
Phillip Webb 已提交
703 704 705 706
	}

	@Test
	public void resolveTypeVaraibleFromMethodReturnWithInstanceClass() throws Exception {
J
Juergen Hoeller 已提交
707
		ResolvableType type = ResolvableType.forMethodReturnType(
P
Phillip Webb 已提交
708
				Methods.class.getMethod("typedReturn"), TypedMethods.class);
709
		assertThat(type.resolve()).isEqualTo(String.class);
P
Phillip Webb 已提交
710 711 712 713 714 715
	}

	@Test
	public void resolveTypeVaraibleFromSimpleInterfaceType() {
		ResolvableType type = ResolvableType.forClass(
				MySimpleInterfaceType.class).as(MyInterfaceType.class);
716
		assertThat(type.resolveGeneric()).isEqualTo(String.class);
P
Phillip Webb 已提交
717 718 719 720 721 722
	}

	@Test
	public void resolveTypeVaraibleFromSimpleCollectionInterfaceType() {
		ResolvableType type = ResolvableType.forClass(
				MyCollectionInterfaceType.class).as(MyInterfaceType.class);
723 724
		assertThat(type.resolveGeneric()).isEqualTo(Collection.class);
		assertThat(type.resolveGeneric(0, 0)).isEqualTo(String.class);
P
Phillip Webb 已提交
725 726 727 728 729 730
	}

	@Test
	public void resolveTypeVaraibleFromSimpleSuperclassType() {
		ResolvableType type = ResolvableType.forClass(
				MySimpleSuperclassType.class).as(MySuperclassType.class);
731
		assertThat(type.resolveGeneric()).isEqualTo(String.class);
P
Phillip Webb 已提交
732 733 734 735 736 737
	}

	@Test
	public void resolveTypeVaraibleFromSimpleCollectionSuperclassType() {
		ResolvableType type = ResolvableType.forClass(
				MyCollectionSuperclassType.class).as(MySuperclassType.class);
738 739
		assertThat(type.resolveGeneric()).isEqualTo(Collection.class);
		assertThat(type.resolveGeneric(0, 0)).isEqualTo(String.class);
P
Phillip Webb 已提交
740 741 742 743 744 745
	}

	@Test
	public void resolveTypeVariableFromFieldTypeWithImplementsClass() throws Exception {
		ResolvableType type = ResolvableType.forField(
				Fields.class.getField("parameterizedType"), TypedFields.class);
746 747
		assertThat(type.resolve()).isEqualTo(List.class);
		assertThat(type.getGeneric().resolve()).isEqualTo(String.class);
P
Phillip Webb 已提交
748 749
	}

750 751 752 753 754 755
	@Test
	public void resolveTypeVariableFromFieldTypeWithImplementsType() throws Exception {
		ResolvableType implementationType = ResolvableType.forClassWithGenerics(
				Fields.class, Integer.class);
		ResolvableType type = ResolvableType.forField(
				Fields.class.getField("parameterizedType"), implementationType);
756 757
		assertThat(type.resolve()).isEqualTo(List.class);
		assertThat(type.getGeneric().resolve()).isEqualTo(Integer.class);
758 759
	}

P
Phillip Webb 已提交
760 761 762
	@Test
	public void resolveTypeVariableFromSuperType() throws Exception {
		ResolvableType type = ResolvableType.forClass(ExtendsList.class);
763 764 765
		assertThat(type.resolve()).isEqualTo(ExtendsList.class);
		assertThat(type.asCollection().resolveGeneric())
			.isEqualTo(CharSequence.class);
P
Phillip Webb 已提交
766 767 768 769 770 771
	}

	@Test
	public void resolveTypeVariableFromClassWithImplementsClass() throws Exception {
		ResolvableType type = ResolvableType.forClass(
				MySuperclassType.class, MyCollectionSuperclassType.class);
772 773
		assertThat(type.resolveGeneric()).isEqualTo(Collection.class);
		assertThat(type.resolveGeneric(0, 0)).isEqualTo(String.class);
P
Phillip Webb 已提交
774 775 776 777 778 779
	}

	@Test
	public void resolveTypeVariableFromConstructorParameter() throws Exception {
		Constructor<?> constructor = Constructors.class.getConstructor(List.class);
		ResolvableType type = ResolvableType.forConstructorParameter(constructor, 0);
780 781
		assertThat(type.resolve()).isEqualTo(List.class);
		assertThat(type.resolveGeneric(0)).isEqualTo(CharSequence.class);
P
Phillip Webb 已提交
782 783 784 785 786 787
	}

	@Test
	public void resolveUnknownTypeVariableFromConstructorParameter() throws Exception {
		Constructor<?> constructor = Constructors.class.getConstructor(Map.class);
		ResolvableType type = ResolvableType.forConstructorParameter(constructor, 0);
788 789
		assertThat(type.resolve()).isEqualTo(Map.class);
		assertThat(type.resolveGeneric(0)).isNull();
P
Phillip Webb 已提交
790 791 792 793 794 795 796
	}

	@Test
	public void resolveTypeVariableFromConstructorParameterWithImplementsClass() throws Exception {
		Constructor<?> constructor = Constructors.class.getConstructor(Map.class);
		ResolvableType type = ResolvableType.forConstructorParameter(
				constructor, 0, TypedConstructors.class);
797 798
		assertThat(type.resolve()).isEqualTo(Map.class);
		assertThat(type.resolveGeneric(0)).isEqualTo(String.class);
P
Phillip Webb 已提交
799 800 801 802 803 804
	}

	@Test
	public void resolveTypeVariableFromMethodParameter() throws Exception {
		Method method = Methods.class.getMethod("typedParameter", Object.class);
		ResolvableType type = ResolvableType.forMethodParameter(method, 0);
805 806
		assertThat(type.resolve()).isNull();
		assertThat(type.getType().toString()).isEqualTo("T");
P
Phillip Webb 已提交
807 808 809 810 811 812
	}

	@Test
	public void resolveTypeVariableFromMethodParameterWithImplementsClass() throws Exception {
		Method method = Methods.class.getMethod("typedParameter", Object.class);
		ResolvableType type = ResolvableType.forMethodParameter(method, 0, TypedMethods.class);
813 814
		assertThat(type.resolve()).isEqualTo(String.class);
		assertThat(type.getType().toString()).isEqualTo("T");
P
Phillip Webb 已提交
815 816 817 818 819
	}

	@Test
	public void resolveTypeVariableFromMethodParameterType() throws Exception {
		Method method = Methods.class.getMethod("typedParameter", Object.class);
820
		MethodParameter methodParameter = MethodParameter.forExecutable(method, 0);
P
Phillip Webb 已提交
821
		ResolvableType type = ResolvableType.forMethodParameter(methodParameter);
822 823
		assertThat(type.resolve()).isNull();
		assertThat(type.getType().toString()).isEqualTo("T");
P
Phillip Webb 已提交
824 825 826
	}

	@Test
J
Juergen Hoeller 已提交
827
	public void resolveTypeVariableFromMethodParameterTypeWithImplementsClass() throws Exception {
P
Phillip Webb 已提交
828
		Method method = Methods.class.getMethod("typedParameter", Object.class);
829
		MethodParameter methodParameter = MethodParameter.forExecutable(method, 0);
J
Juergen Hoeller 已提交
830 831
		methodParameter.setContainingClass(TypedMethods.class);
		ResolvableType type = ResolvableType.forMethodParameter(methodParameter);
832 833
		assertThat(type.resolve()).isEqualTo(String.class);
		assertThat(type.getType().toString()).isEqualTo("T");
P
Phillip Webb 已提交
834 835
	}

836 837 838
	@Test
	public void resolveTypeVariableFromMethodParameterTypeWithImplementsType() throws Exception {
		Method method = Methods.class.getMethod("typedParameter", Object.class);
839
		MethodParameter methodParameter = MethodParameter.forExecutable(method, 0);
840 841
		ResolvableType implementationType = ResolvableType.forClassWithGenerics(Methods.class, Integer.class);
		ResolvableType type = ResolvableType.forMethodParameter(methodParameter, implementationType);
842 843
		assertThat(type.resolve()).isEqualTo(Integer.class);
		assertThat(type.getType().toString()).isEqualTo("T");
844 845
	}

P
Phillip Webb 已提交
846 847 848
	@Test
	public void resolveTypeVariableFromMethodReturn() throws Exception {
		Method method = Methods.class.getMethod("typedReturn");
J
Juergen Hoeller 已提交
849
		ResolvableType type = ResolvableType.forMethodReturnType(method);
850 851
		assertThat(type.resolve()).isNull();
		assertThat(type.getType().toString()).isEqualTo("T");
P
Phillip Webb 已提交
852 853 854 855 856
	}

	@Test
	public void resolveTypeVariableFromMethodReturnWithImplementsClass() throws Exception {
		Method method = Methods.class.getMethod("typedReturn");
J
Juergen Hoeller 已提交
857
		ResolvableType type = ResolvableType.forMethodReturnType(method, TypedMethods.class);
858 859
		assertThat(type.resolve()).isEqualTo(String.class);
		assertThat(type.getType().toString()).isEqualTo("T");
P
Phillip Webb 已提交
860 861 862 863 864 865
	}

	@Test
	public void resolveTypeVariableFromType() throws Exception {
		Type sourceType = Methods.class.getMethod("typedReturn").getGenericReturnType();
		ResolvableType type = ResolvableType.forType(sourceType);
866 867
		assertThat(type.resolve()).isNull();
		assertThat(type.getType().toString()).isEqualTo("T");
P
Phillip Webb 已提交
868 869 870 871 872 873
	}

	@Test
	public void resolveTypeVariableFromTypeWithVariableResolver() throws Exception {
		Type sourceType = Methods.class.getMethod("typedReturn").getGenericReturnType();
		ResolvableType type = ResolvableType.forType(
P
Phillip Webb 已提交
874
				sourceType, ResolvableType.forClass(TypedMethods.class).as(Methods.class).asVariableResolver());
875 876
		assertThat(type.resolve()).isEqualTo(String.class);
		assertThat(type.getType().toString()).isEqualTo("T");
P
Phillip Webb 已提交
877 878 879 880
	}

	@Test
	public void resolveTypeWithCustomVariableResolver() throws Exception {
P
Phillip Webb 已提交
881
		VariableResolver variableResolver = mock(VariableResolver.class);
882
		given(variableResolver.getSource()).willReturn(this);
P
Phillip Webb 已提交
883
		ResolvableType longType = ResolvableType.forClass(Long.class);
J
Juergen Hoeller 已提交
884
		given(variableResolver.resolveVariable(any())).willReturn(longType);
P
Phillip Webb 已提交
885 886 887 888 889 890

		ResolvableType variable = ResolvableType.forType(
				Fields.class.getField("typeVariableType").getGenericType(), variableResolver);
		ResolvableType parameterized = ResolvableType.forType(
				Fields.class.getField("parameterizedType").getGenericType(), variableResolver);

891 892 893
		assertThat(variable.resolve()).isEqualTo(Long.class);
		assertThat(parameterized.resolve()).isEqualTo(List.class);
		assertThat(parameterized.resolveGeneric()).isEqualTo(Long.class);
P
Phillip Webb 已提交
894
		verify(variableResolver, atLeastOnce()).resolveVariable(this.typeVariableCaptor.capture());
895
		assertThat(this.typeVariableCaptor.getValue().getName()).isEqualTo("T");
P
Phillip Webb 已提交
896 897
	}

898 899 900 901
	@Test
	public void resolveTypeVariableFromReflectiveParameterizedTypeReference() throws Exception {
		Type sourceType = Methods.class.getMethod("typedReturn").getGenericReturnType();
		ResolvableType type = ResolvableType.forType(ParameterizedTypeReference.forType(sourceType));
902 903
		assertThat(type.resolve()).isNull();
		assertThat(type.getType().toString()).isEqualTo("T");
904 905 906 907 908 909 910
	}

	@Test
	public void resolveTypeVariableFromDeclaredParameterizedTypeReference() throws Exception {
		Type sourceType = Methods.class.getMethod("charSequenceReturn").getGenericReturnType();
		ResolvableType reflectiveType = ResolvableType.forType(sourceType);
		ResolvableType declaredType = ResolvableType.forType(new ParameterizedTypeReference<List<CharSequence>>() {});
911
		assertThat(declaredType).isEqualTo(reflectiveType);
912 913
	}

P
Phillip Webb 已提交
914 915
	@Test
	public void toStrings() throws Exception {
916
		assertThat(ResolvableType.NONE.toString()).isEqualTo("?");
P
Phillip Webb 已提交
917

918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
		assertThat(forField("classType")).hasToString("java.util.List<?>");
		assertThat(forField("typeVariableType")).hasToString("?");
		assertThat(forField("parameterizedType")).hasToString("java.util.List<?>");
		assertThat(forField("arrayClassType")).hasToString("java.util.List<?>[]");
		assertThat(forField("genericArrayType")).hasToString("java.util.List<java.lang.String>[]");
		assertThat(forField("genericMultiArrayType")).hasToString("java.util.List<java.lang.String>[][][]");
		assertThat(forField("wildcardType")).hasToString("java.util.List<java.lang.Number>");
		assertThat(forField("wildcardSuperType")).hasToString("java.util.List<java.lang.Number>");
		assertThat(forField("charSequenceList")).hasToString("java.util.List<java.lang.CharSequence>");
		assertThat(forField("stringList")).hasToString("java.util.List<java.lang.String>");
		assertThat(forField("stringListList")).hasToString("java.util.List<java.util.List<java.lang.String>>");
		assertThat(forField("stringArrayList")).hasToString("java.util.List<java.lang.String[]>");
		assertThat(forField("stringIntegerMultiValueMap")).hasToString("org.springframework.util.MultiValueMap<java.lang.String, java.lang.Integer>");
		assertThat(forField("stringIntegerMultiValueMapSwitched")).hasToString(VariableNameSwitch.class.getName() + "<java.lang.Integer, java.lang.String>");
		assertThat(forField("listOfListOfUnknown")).hasToString("java.util.List<java.util.List<?>>");
P
Phillip Webb 已提交
933

934 935
		assertThat(forTypedField("typeVariableType")).hasToString("java.lang.String");
		assertThat(forTypedField("parameterizedType")).hasToString("java.util.List<java.lang.String>");
P
Phillip Webb 已提交
936

937 938
		assertThat(ResolvableType.forClass(ListOfGenericArray.class).toString()).isEqualTo(ListOfGenericArray.class.getName());
		assertThat(ResolvableType.forClass(List.class, ListOfGenericArray.class).toString()).isEqualTo("java.util.List<java.util.List<java.lang.String>[]>");
P
Phillip Webb 已提交
939 940
	}

941 942 943 944 945 946
	@Test
	public void getSource() throws Exception {
		Class<?> classType = MySimpleInterfaceType.class;
		Field basicField = Fields.class.getField("classType");
		Field field = Fields.class.getField("charSequenceList");
		Method method = Methods.class.getMethod("charSequenceParameter", List.class);
947
		MethodParameter methodParameter = MethodParameter.forExecutable(method, 0);
948 949 950 951 952 953
		assertThat(ResolvableType.forField(basicField).getSource()).isEqualTo(basicField);
		assertThat(ResolvableType.forField(field).getSource()).isEqualTo(field);
		assertThat(ResolvableType.forMethodParameter(methodParameter).getSource()).isEqualTo(methodParameter);
		assertThat(ResolvableType.forMethodParameter(method, 0).getSource()).isEqualTo(methodParameter);
		assertThat(ResolvableType.forClass(classType).getSource()).isEqualTo(classType);
		assertThat(ResolvableType.forClass(classType).getSuperType().getSource()).isEqualTo(classType.getGenericSuperclass());
954 955
	}

P
Phillip Webb 已提交
956 957 958
	@Test
	public void resolveFromOuterClass() throws Exception {
		Field field = EnclosedInParameterizedType.InnerTyped.class.getField("field");
J
Juergen Hoeller 已提交
959
		ResolvableType type = ResolvableType.forField(field, TypedEnclosedInParameterizedType.TypedInnerTyped.class);
960
		assertThat(type.resolve()).isEqualTo(Integer.class);
P
Phillip Webb 已提交
961 962
	}

P
Phillip Webb 已提交
963 964 965
	@Test
	public void resolveFromClassWithGenerics() throws Exception {
		ResolvableType type = ResolvableType.forClassWithGenerics(List.class, ResolvableType.forClassWithGenerics(List.class, String.class));
966 967 968 969 970
		assertThat(type.asCollection().toString()).isEqualTo("java.util.Collection<java.util.List<java.lang.String>>");
		assertThat(type.asCollection().getGeneric().toString()).isEqualTo("java.util.List<java.lang.String>");
		assertThat(type.asCollection().getGeneric().asCollection().toString()).isEqualTo("java.util.Collection<java.lang.String>");
		assertThat(type.toString()).isEqualTo("java.util.List<java.util.List<java.lang.String>>");
		assertThat(type.asCollection().getGeneric().getGeneric().resolve()).isEqualTo(String.class);
P
Phillip Webb 已提交
971 972
	}

P
Phillip Webb 已提交
973 974
	@Test
	public void isAssignableFromMustNotBeNull() throws Exception {
975 976 977
		assertThatIllegalArgumentException().isThrownBy(() ->
				ResolvableType.forClass(Object.class).isAssignableFrom((ResolvableType) null))
			.withMessageContaining("Type must not be null");
P
Phillip Webb 已提交
978 979 980 981 982
	}

	@Test
	public void isAssignableFromForNone() throws Exception {
		ResolvableType objectType = ResolvableType.forClass(Object.class);
983 984
		assertThat(objectType.isAssignableFrom(ResolvableType.NONE)).isEqualTo(false);
		assertThat(ResolvableType.NONE.isAssignableFrom(objectType)).isEqualTo(false);
P
Phillip Webb 已提交
985 986 987 988 989 990 991 992
	}

	@Test
	public void isAssignableFromForClassAndClass() throws Exception {
		ResolvableType objectType = ResolvableType.forClass(Object.class);
		ResolvableType charSequenceType = ResolvableType.forClass(CharSequence.class);
		ResolvableType stringType = ResolvableType.forClass(String.class);

993 994 995
		assertThatResolvableType(objectType).isAssignableFrom(objectType, charSequenceType, stringType);
		assertThatResolvableType(charSequenceType).isAssignableFrom(charSequenceType, stringType).isNotAssignableFrom(objectType);
		assertThatResolvableType(stringType).isAssignableFrom(stringType).isNotAssignableFrom(objectType, charSequenceType);
996

997 998 999 1000 1001 1002
		assertThat(objectType.isAssignableFrom(String.class)).isTrue();
		assertThat(objectType.isAssignableFrom(StringBuilder.class)).isTrue();
		assertThat(charSequenceType.isAssignableFrom(String.class)).isTrue();
		assertThat(charSequenceType.isAssignableFrom(StringBuilder.class)).isTrue();
		assertThat(stringType.isAssignableFrom(String.class)).isTrue();
		assertThat(stringType.isAssignableFrom(StringBuilder.class)).isFalse();
1003

1004 1005 1006 1007 1008 1009
		assertThat(objectType.isInstance("a String")).isTrue();
		assertThat(objectType.isInstance(new StringBuilder("a StringBuilder"))).isTrue();
		assertThat(charSequenceType.isInstance("a String")).isTrue();
		assertThat(charSequenceType.isInstance(new StringBuilder("a StringBuilder"))).isTrue();
		assertThat(stringType.isInstance("a String")).isTrue();
		assertThat(stringType.isInstance(new StringBuilder("a StringBuilder"))).isFalse();
P
Phillip Webb 已提交
1010 1011 1012 1013 1014 1015
	}

	@Test
	public void isAssignableFromCannotBeResolved() throws Exception {
		ResolvableType objectType = ResolvableType.forClass(Object.class);
		ResolvableType unresolvableVariable = ResolvableType.forField(AssignmentBase.class.getField("o"));
1016 1017 1018
		assertThat(unresolvableVariable.resolve()).isNull();
		assertThatResolvableType(objectType).isAssignableFrom(unresolvableVariable);
		assertThatResolvableType(unresolvableVariable).isAssignableFrom(objectType);
P
Phillip Webb 已提交
1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
	}

	@Test
	public void isAssignableFromForClassAndSimpleVariable() throws Exception {
		ResolvableType objectType = ResolvableType.forClass(Object.class);
		ResolvableType charSequenceType = ResolvableType.forClass(CharSequence.class);
		ResolvableType stringType = ResolvableType.forClass(String.class);

		ResolvableType objectVariable = ResolvableType.forField(AssignmentBase.class.getField("o"), Assignment.class);
		ResolvableType charSequenceVariable = ResolvableType.forField(AssignmentBase.class.getField("c"), Assignment.class);
		ResolvableType stringVariable = ResolvableType.forField(AssignmentBase.class.getField("s"), Assignment.class);

1031 1032 1033
		assertThatResolvableType(objectType).isAssignableFrom(objectVariable, charSequenceVariable, stringVariable);
		assertThatResolvableType(charSequenceType).isAssignableFrom(charSequenceVariable, stringVariable).isNotAssignableFrom(objectVariable);
		assertThatResolvableType(stringType).isAssignableFrom(stringVariable).isNotAssignableFrom(objectVariable, charSequenceVariable);
P
Phillip Webb 已提交
1034

1035 1036 1037
		assertThatResolvableType(objectVariable).isAssignableFrom(objectType, charSequenceType, stringType);
		assertThatResolvableType(charSequenceVariable).isAssignableFrom(charSequenceType, stringType).isNotAssignableFrom(objectType);
		assertThatResolvableType(stringVariable).isAssignableFrom(stringType).isNotAssignableFrom(objectType, charSequenceType);
P
Phillip Webb 已提交
1038

1039 1040 1041
		assertThatResolvableType(objectVariable).isAssignableFrom(objectVariable, charSequenceVariable, stringVariable);
		assertThatResolvableType(charSequenceVariable).isAssignableFrom(charSequenceVariable, stringVariable).isNotAssignableFrom(objectVariable);
		assertThatResolvableType(stringVariable).isAssignableFrom(stringVariable).isNotAssignableFrom(objectVariable, charSequenceVariable);
P
Phillip Webb 已提交
1042 1043 1044 1045 1046 1047 1048
	}

	@Test
	public void isAssignableFromForSameClassNonExtendsGenerics() throws Exception {
		ResolvableType objectList = ResolvableType.forField(AssignmentBase.class.getField("listo"), Assignment.class);
		ResolvableType stringList = ResolvableType.forField(AssignmentBase.class.getField("lists"), Assignment.class);

1049 1050 1051
		assertThatResolvableType(stringList).isNotAssignableFrom(objectList);
		assertThatResolvableType(objectList).isNotAssignableFrom(stringList);
		assertThatResolvableType(stringList).isAssignableFrom(stringList);
P
Phillip Webb 已提交
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076
	}

	@Test
	public void isAssignableFromForSameClassExtendsGenerics() throws Exception {

		// Generic assignment can be a little confusing, given:
		//
		// List<CharSequence> c1, List<? extends CharSequence> c2, List<String> s;
		//
		// c2 = s; is allowed and is often used for argument input, for example
		// see List.addAll(). You can get items from c2 but you cannot add items without
		// getting a generic type 'is not applicable for the arguments' error. This makes
		// sense since if you added a StringBuffer to c2 it would break the rules on s.
		//
		// c1 = s; not allowed. Since there is no '? extends' to cause the generic
		// 'is not applicable for the arguments' error when adding (which would pollute
		// s).

		ResolvableType objectList = ResolvableType.forField(AssignmentBase.class.getField("listo"), Assignment.class);
		ResolvableType charSequenceList = ResolvableType.forField(AssignmentBase.class.getField("listc"), Assignment.class);
		ResolvableType stringList = ResolvableType.forField(AssignmentBase.class.getField("lists"), Assignment.class);
		ResolvableType extendsObjectList = ResolvableType.forField(AssignmentBase.class.getField("listxo"), Assignment.class);
		ResolvableType extendsCharSequenceList = ResolvableType.forField(AssignmentBase.class.getField("listxc"), Assignment.class);
		ResolvableType extendsStringList = ResolvableType.forField(AssignmentBase.class.getField("listxs"), Assignment.class);

1077 1078 1079 1080 1081 1082 1083 1084 1085
		assertThatResolvableType(objectList).isNotAssignableFrom(extendsObjectList, extendsCharSequenceList, extendsStringList);
		assertThatResolvableType(charSequenceList).isNotAssignableFrom(extendsObjectList, extendsCharSequenceList, extendsStringList);
		assertThatResolvableType(stringList).isNotAssignableFrom(extendsObjectList, extendsCharSequenceList, extendsStringList);
		assertThatResolvableType(extendsObjectList).isAssignableFrom(objectList, charSequenceList, stringList);
		assertThatResolvableType(extendsObjectList).isAssignableFrom(extendsObjectList, extendsCharSequenceList, extendsStringList);
		assertThatResolvableType(extendsCharSequenceList).isAssignableFrom(extendsCharSequenceList, extendsStringList).isNotAssignableFrom(extendsObjectList);
		assertThatResolvableType(extendsCharSequenceList).isAssignableFrom(charSequenceList, stringList).isNotAssignableFrom(objectList);
		assertThatResolvableType(extendsStringList).isAssignableFrom(extendsStringList).isNotAssignableFrom(extendsObjectList, extendsCharSequenceList);
		assertThatResolvableType(extendsStringList).isAssignableFrom(stringList).isNotAssignableFrom(objectList, charSequenceList);
P
Phillip Webb 已提交
1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
	}

	@Test
	public void isAssignableFromForDifferentClassesWithGenerics() throws Exception {
		ResolvableType extendsCharSequenceCollection = ResolvableType.forField(AssignmentBase.class.getField("collectionxc"), Assignment.class);
		ResolvableType charSequenceCollection = ResolvableType.forField(AssignmentBase.class.getField("collectionc"), Assignment.class);
		ResolvableType charSequenceList = ResolvableType.forField(AssignmentBase.class.getField("listc"), Assignment.class);
		ResolvableType extendsCharSequenceList = ResolvableType.forField(AssignmentBase.class.getField("listxc"), Assignment.class);
		ResolvableType extendsStringList = ResolvableType.forField(AssignmentBase.class.getField("listxs"), Assignment.class);

1096 1097 1098 1099 1100
		assertThatResolvableType(extendsCharSequenceCollection).isAssignableFrom(charSequenceCollection, charSequenceList, extendsCharSequenceList, extendsStringList);
		assertThatResolvableType(charSequenceCollection).isAssignableFrom(charSequenceList).isNotAssignableFrom(extendsCharSequenceList, extendsStringList);
		assertThatResolvableType(charSequenceList).isNotAssignableFrom(extendsCharSequenceCollection, charSequenceCollection);
		assertThatResolvableType(extendsCharSequenceList).isNotAssignableFrom(extendsCharSequenceCollection, charSequenceCollection);
		assertThatResolvableType(extendsStringList).isNotAssignableFrom(charSequenceCollection, charSequenceList, extendsCharSequenceList);
P
Phillip Webb 已提交
1101 1102 1103 1104 1105 1106 1107 1108 1109
	}

	@Test
	public void isAssignableFromForArrays() throws Exception {
		ResolvableType object = ResolvableType.forField(AssignmentBase.class.getField("o"), Assignment.class);
		ResolvableType objectArray = ResolvableType.forField(AssignmentBase.class.getField("oarray"), Assignment.class);
		ResolvableType charSequenceArray = ResolvableType.forField(AssignmentBase.class.getField("carray"), Assignment.class);
		ResolvableType stringArray = ResolvableType.forField(AssignmentBase.class.getField("sarray"), Assignment.class);

1110 1111 1112 1113
		assertThatResolvableType(object).isAssignableFrom(objectArray, charSequenceArray, stringArray);
		assertThatResolvableType(objectArray).isAssignableFrom(objectArray, charSequenceArray, stringArray).isNotAssignableFrom(object);
		assertThatResolvableType(charSequenceArray).isAssignableFrom(charSequenceArray, stringArray).isNotAssignableFrom(object, objectArray);
		assertThatResolvableType(stringArray).isAssignableFrom(stringArray).isNotAssignableFrom(object, objectArray, charSequenceArray);
P
Phillip Webb 已提交
1114 1115 1116 1117 1118 1119 1120
	}

	@Test
	public void isAssignableFromForWildcards() throws Exception {
		ResolvableType object = ResolvableType.forClass(Object.class);
		ResolvableType charSequence = ResolvableType.forClass(CharSequence.class);
		ResolvableType string = ResolvableType.forClass(String.class);
1121
		ResolvableType extendsAnon = ResolvableType.forField(AssignmentBase.class.getField("listAnon"), Assignment.class).getGeneric();
P
Phillip Webb 已提交
1122 1123 1124 1125 1126 1127 1128 1129 1130 1131
		ResolvableType extendsObject = ResolvableType.forField(AssignmentBase.class.getField("listxo"), Assignment.class).getGeneric();
		ResolvableType extendsCharSequence = ResolvableType.forField(AssignmentBase.class.getField("listxc"), Assignment.class).getGeneric();
		ResolvableType extendsString = ResolvableType.forField(AssignmentBase.class.getField("listxs"), Assignment.class).getGeneric();
		ResolvableType superObject = ResolvableType.forField(AssignmentBase.class.getField("listso"), Assignment.class).getGeneric();
		ResolvableType superCharSequence = ResolvableType.forField(AssignmentBase.class.getField("listsc"), Assignment.class).getGeneric();
		ResolvableType superString = ResolvableType.forField(AssignmentBase.class.getField("listss"), Assignment.class).getGeneric();

		// Language Spec 4.5.1. Type Arguments and Wildcards

		// ? extends T <= ? extends S if T <: S
1132 1133
		assertThatResolvableType(extendsCharSequence).isAssignableFrom(extendsCharSequence, extendsString).isNotAssignableFrom(extendsObject);
		assertThatResolvableType(extendsCharSequence).isAssignableFrom(charSequence, string).isNotAssignableFrom(object);
P
Phillip Webb 已提交
1134 1135

		// ? super T <= ? super S if S <: T
1136 1137
		assertThatResolvableType(superCharSequence).isAssignableFrom(superObject, superCharSequence).isNotAssignableFrom(superString);
		assertThatResolvableType(superCharSequence).isAssignableFrom(object, charSequence).isNotAssignableFrom(string);
P
Phillip Webb 已提交
1138 1139

		// [Implied] super / extends cannot be mixed
1140 1141
		assertThatResolvableType(superCharSequence).isNotAssignableFrom(extendsObject, extendsCharSequence, extendsString);
		assertThatResolvableType(extendsCharSequence).isNotAssignableFrom(superObject, superCharSequence, superString);
P
Phillip Webb 已提交
1142 1143

		// T <= T
1144
		assertThatResolvableType(charSequence).isAssignableFrom(charSequence, string).isNotAssignableFrom(object);
P
Phillip Webb 已提交
1145 1146

		// T <= ? extends T
1147 1148 1149
		assertThatResolvableType(extendsCharSequence).isAssignableFrom(charSequence, string).isNotAssignableFrom(object);
		assertThatResolvableType(charSequence).isNotAssignableFrom(extendsObject, extendsCharSequence, extendsString);
		assertThatResolvableType(extendsAnon).isAssignableFrom(object, charSequence, string);
P
Phillip Webb 已提交
1150 1151

		// T <= ? super T
1152 1153
		assertThatResolvableType(superCharSequence).isAssignableFrom(object, charSequence).isNotAssignableFrom(string);
		assertThatResolvableType(charSequence).isNotAssignableFrom(superObject, superCharSequence, superString);
P
Phillip Webb 已提交
1154 1155 1156 1157 1158 1159 1160 1161 1162
	}

	@Test
	public void isAssignableFromForComplexWildcards() throws Exception {
		ResolvableType complex1 = ResolvableType.forField(AssignmentBase.class.getField("complexWildcard1"));
		ResolvableType complex2 = ResolvableType.forField(AssignmentBase.class.getField("complexWildcard2"));
		ResolvableType complex3 = ResolvableType.forField(AssignmentBase.class.getField("complexWildcard3"));
		ResolvableType complex4 = ResolvableType.forField(AssignmentBase.class.getField("complexWildcard4"));

1163 1164 1165 1166
		assertThatResolvableType(complex1).isAssignableFrom(complex2);
		assertThatResolvableType(complex2).isNotAssignableFrom(complex1);
		assertThatResolvableType(complex3).isAssignableFrom(complex4);
		assertThatResolvableType(complex4).isNotAssignableFrom(complex3);
P
Phillip Webb 已提交
1167 1168 1169 1170 1171 1172
	}

	@Test
	public void hashCodeAndEquals() throws Exception {
		ResolvableType forClass = ResolvableType.forClass(List.class);
		ResolvableType forFieldDirect = ResolvableType.forField(Fields.class.getDeclaredField("stringList"));
P
Phillip Webb 已提交
1173
		ResolvableType forFieldViaType = ResolvableType.forType(Fields.class.getDeclaredField("stringList").getGenericType(), (VariableResolver) null);
P
Phillip Webb 已提交
1174 1175
		ResolvableType forFieldWithImplementation = ResolvableType.forField(Fields.class.getDeclaredField("stringList"), TypedFields.class);

1176 1177 1178 1179
		assertThat(forClass).isEqualTo(forClass);
		assertThat(forClass.hashCode()).isEqualTo(forClass.hashCode());
		assertThat(forClass).isNotEqualTo(forFieldDirect);
		assertThat(forClass).isNotEqualTo(forFieldWithImplementation);
P
Phillip Webb 已提交
1180

1181 1182 1183
		assertThat(forFieldDirect).isEqualTo(forFieldDirect);
		assertThat(forFieldDirect).isNotEqualTo(forFieldViaType);
		assertThat(forFieldDirect).isNotEqualTo(forFieldWithImplementation);
P
Phillip Webb 已提交
1184 1185 1186 1187 1188
	}

	@Test
	public void javaDocSample() throws Exception {
		ResolvableType t = ResolvableType.forField(getClass().getDeclaredField("myMap"));
1189 1190 1191 1192 1193 1194 1195 1196 1197
		assertThat(t.toString()).isEqualTo("java.util.HashMap<java.lang.Integer, java.util.List<java.lang.String>>");
		assertThat(t.getType().getTypeName()).isEqualTo("java.util.HashMap<java.lang.Integer, java.util.List<java.lang.String>>");
		assertThat(t.getType().toString()).isEqualTo("java.util.HashMap<java.lang.Integer, java.util.List<java.lang.String>>");
		assertThat(t.getSuperType().toString()).isEqualTo("java.util.AbstractMap<java.lang.Integer, java.util.List<java.lang.String>>");
		assertThat(t.asMap().toString()).isEqualTo("java.util.Map<java.lang.Integer, java.util.List<java.lang.String>>");
		assertThat(t.getGeneric(0).resolve()).isEqualTo(Integer.class);
		assertThat(t.getGeneric(1).resolve()).isEqualTo(List.class);
		assertThat(t.getGeneric(1).toString()).isEqualTo("java.util.List<java.lang.String>");
		assertThat(t.resolveGeneric(1, 0)).isEqualTo(String.class);
P
Phillip Webb 已提交
1198 1199
	}

P
Phillip Webb 已提交
1200 1201 1202 1203
	@Test
	public void forClassWithGenerics() throws Exception {
		ResolvableType elementType = ResolvableType.forClassWithGenerics(Map.class, Integer.class, String.class);
		ResolvableType listType = ResolvableType.forClassWithGenerics(List.class, elementType);
1204 1205 1206
		assertThat(listType.toString()).isEqualTo("java.util.List<java.util.Map<java.lang.Integer, java.lang.String>>");
		assertThat(listType.getType().getTypeName()).isEqualTo("java.util.List<java.util.Map<java.lang.Integer, java.lang.String>>");
		assertThat(listType.getType().toString()).isEqualTo("java.util.List<java.util.Map<java.lang.Integer, java.lang.String>>");
P
Phillip Webb 已提交
1207 1208 1209 1210 1211
	}

	@Test
	public void classWithGenericsAs() throws Exception {
		ResolvableType type = ResolvableType.forClassWithGenerics(MultiValueMap.class, Integer.class, String.class);
1212
		assertThat(type.asMap().toString()).isEqualTo("java.util.Map<java.lang.Integer, java.util.List<java.lang.String>>");
P
Phillip Webb 已提交
1213 1214 1215 1216
	}

	@Test
	public void forClassWithMismatchedGenerics() throws Exception {
1217 1218 1219
		assertThatIllegalArgumentException().isThrownBy(() ->
				ResolvableType.forClassWithGenerics(Map.class, Integer.class))
			.withMessageContaining("Mismatched number of generics specified");
P
Phillip Webb 已提交
1220 1221 1222 1223 1224 1225
	}

	@Test
	public void forArrayComponent() throws Exception {
		ResolvableType elementType = ResolvableType.forField(Fields.class.getField("stringList"));
		ResolvableType type = ResolvableType.forArrayComponent(elementType);
1226 1227
		assertThat(type.toString()).isEqualTo("java.util.List<java.lang.String>[]");
		assertThat(type.resolve()).isEqualTo(List[].class);
P
Phillip Webb 已提交
1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238
	}

	@Test
	public void serialize() throws Exception {
		testSerialization(ResolvableType.forClass(List.class));
		testSerialization(ResolvableType.forField(Fields.class.getField("charSequenceList")));
		testSerialization(ResolvableType.forMethodParameter(Methods.class.getMethod("charSequenceParameter", List.class), 0));
		testSerialization(ResolvableType.forMethodReturnType(Methods.class.getMethod("charSequenceReturn")));
		testSerialization(ResolvableType.forConstructorParameter(Constructors.class.getConstructor(List.class), 0));
		testSerialization(ResolvableType.forField(Fields.class.getField("charSequenceList")).getGeneric());
		ResolvableType deserializedNone = testSerialization(ResolvableType.NONE);
1239
		assertThat(deserializedNone).isSameAs(ResolvableType.NONE);
P
Phillip Webb 已提交
1240 1241
	}

1242 1243 1244
	@Test
	public void canResolveVoid() throws Exception {
		ResolvableType type = ResolvableType.forClass(void.class);
1245
		assertThat(type.resolve()).isEqualTo(void.class);
1246 1247 1248 1249 1250 1251
	}

	@Test
	public void narrow() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("stringList"));
		ResolvableType narrow = ResolvableType.forType(ArrayList.class, type);
1252
		assertThat(narrow.getGeneric().resolve()).isEqualTo(String.class);
1253 1254
	}

1255 1256 1257
	@Test
	public void hasUnresolvableGenerics() throws Exception {
		ResolvableType type = ResolvableType.forField(Fields.class.getField("stringList"));
1258
		assertThat(type.hasUnresolvableGenerics()).isEqualTo(false);
1259 1260 1261 1262 1263
	}

	@Test
	public void hasUnresolvableGenericsBasedOnOwnGenerics() throws Exception {
		ResolvableType type = ResolvableType.forClass(List.class);
1264
		assertThat(type.hasUnresolvableGenerics()).isEqualTo(true);
1265 1266 1267 1268 1269
	}

	@Test
	public void hasUnresolvableGenericsWhenSelfNotResolvable() throws Exception {
		ResolvableType type = ResolvableType.forClass(List.class).getGeneric();
1270
		assertThat(type.hasUnresolvableGenerics()).isEqualTo(false);
1271 1272 1273 1274 1275 1276
	}

	@Test
	public void hasUnresolvableGenericsWhenImplementesRawInterface() throws Exception {
		ResolvableType type = ResolvableType.forClass(MySimpleInterfaceTypeWithImplementsRaw.class);
		for (ResolvableType generic : type.getGenerics()) {
1277
			assertThat(generic.resolve()).isNotNull();
1278
		}
1279
		assertThat(type.hasUnresolvableGenerics()).isEqualTo(true);
1280 1281 1282 1283 1284 1285
	}

	@Test
	public void hasUnresolvableGenericsWhenExtends() throws Exception {
		ResolvableType type = ResolvableType.forClass(ExtendsMySimpleInterfaceTypeWithImplementsRaw.class);
		for (ResolvableType generic : type.getGenerics()) {
1286
			assertThat(generic.resolve()).isNotNull();
1287
		}
1288
		assertThat(type.hasUnresolvableGenerics()).isEqualTo(true);
1289 1290
	}

1291 1292 1293
	@Test
	public void testSpr11219() throws Exception {
		ResolvableType type = ResolvableType.forField(BaseProvider.class.getField("stuff"), BaseProvider.class);
1294 1295
		assertThat(type.getNested(2).isAssignableFrom(ResolvableType.forClass(BaseImplementation.class))).isTrue();
		assertThat(type.toString()).isEqualTo("java.util.Collection<org.springframework.core.ResolvableTypeTests$IBase<?>>");
1296 1297
	}

1298 1299 1300 1301
	@Test
	public void testSpr12701() throws Exception {
		ResolvableType resolvableType = ResolvableType.forClassWithGenerics(Callable.class, String.class);
		Type type = resolvableType.getType();
1302 1303 1304 1305
		assertThat(type).isInstanceOf(ParameterizedType.class);
		assertThat(((ParameterizedType) type).getRawType()).isEqualTo(Callable.class);
		assertThat(((ParameterizedType) type).getActualTypeArguments().length).isEqualTo(1);
		assertThat(((ParameterizedType) type).getActualTypeArguments()[0]).isEqualTo(String.class);
1306 1307
	}

1308 1309 1310 1311 1312
	@Test
	public void testSpr14648() throws Exception {
		ResolvableType collectionClass = ResolvableType.forRawClass(Collection.class);
		ResolvableType setClass = ResolvableType.forRawClass(Set.class);
		ResolvableType fromReturnType = ResolvableType.forMethodReturnType(Methods.class.getMethod("wildcardSet"));
1313 1314
		assertThat(collectionClass.isAssignableFrom(fromReturnType)).isTrue();
		assertThat(setClass.isAssignableFrom(fromReturnType)).isTrue();
1315 1316
	}

1317 1318 1319 1320 1321
	@Test
	public void testSpr16456() throws Exception {
		ResolvableType genericType = ResolvableType.forField(
				UnresolvedWithGenerics.class.getDeclaredField("set")).asCollection();
		ResolvableType type = ResolvableType.forClassWithGenerics(ArrayList.class, genericType.getGeneric());
1322
		assertThat(type.resolveGeneric()).isEqualTo(Integer.class);
1323 1324
	}

1325

P
Phillip Webb 已提交
1326 1327 1328 1329 1330 1331 1332
	private ResolvableType testSerialization(ResolvableType type) throws Exception {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(bos);
		oos.writeObject(type);
		oos.close();
		ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
		ResolvableType read = (ResolvableType) ois.readObject();
1333 1334 1335
		assertThat(read).isEqualTo(type);
		assertThat(read.getType()).isEqualTo(type.getType());
		assertThat(read.resolve()).isEqualTo(type.resolve());
P
Phillip Webb 已提交
1336 1337
		return read;
	}
P
Phillip Webb 已提交
1338

1339 1340
	private ResolvableType forField(String field) throws NoSuchFieldException {
		return ResolvableType.forField(Fields.class.getField(field));
1341 1342
	}

1343 1344
	private ResolvableType forTypedField(String field) throws NoSuchFieldException {
		return ResolvableType.forField(Fields.class.getField(field), TypedFields.class);
1345 1346
	}

1347 1348
	private static ResolvableTypeAssert assertThatResolvableType(ResolvableType type) {
		return new ResolvableTypeAssert(type);
P
Phillip Webb 已提交
1349 1350
	}

J
Juergen Hoeller 已提交
1351

1352 1353 1354 1355
	@SuppressWarnings("unused")
	private HashMap<Integer, List<String>> myMap;


P
Phillip Webb 已提交
1356
	@SuppressWarnings("serial")
P
Phillip Webb 已提交
1357 1358 1359
	static class ExtendsList extends ArrayList<CharSequence> {
	}

P
Phillip Webb 已提交
1360
	@SuppressWarnings("serial")
P
Phillip Webb 已提交
1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399
	static class ExtendsMap extends HashMap<String, Integer> {
	}


	static class Fields<T> {

		public List classType;

		public T typeVariableType;

		public List<T> parameterizedType;

		public List[] arrayClassType;

		public List<String>[] genericArrayType;

		public List<String>[][][] genericMultiArrayType;

		public List<? extends Number> wildcardType;

		public List<? super Number> wildcardSuperType = new ArrayList<Object>();

		public List<CharSequence> charSequenceList;

		public List<String> stringList;

		public List<List<String>> stringListList;

		public List<String[]> stringArrayList;

		public MultiValueMap<String, Integer> stringIntegerMultiValueMap;

		public VariableNameSwitch<Integer, String> stringIntegerMultiValueMapSwitched;

		public List<List> listOfListOfUnknown;

		@SuppressWarnings("unused")
		private List<String> privateField;

1400 1401 1402
		@SuppressWarnings("unused")
		private List<String> otherPrivateField;

P
Phillip Webb 已提交
1403 1404
		public Map<Map<String, Integer>, Map<Byte, Long>> nested;

1405
		public T[] variableTypeGenericArray;
P
Phillip Webb 已提交
1406 1407 1408 1409 1410 1411 1412
	}


	static class TypedFields extends Fields<String> {
	}


1413
	interface Methods<T> {
P
Phillip Webb 已提交
1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425

		List<CharSequence> charSequenceReturn();

		void charSequenceParameter(List<CharSequence> cs);

		<R extends CharSequence & Serializable> R boundedTypeVaraibleResult();

		void nested(Map<Map<String, Integer>, Map<Byte, Long>> p);

		void typedParameter(T p);

		T typedReturn();
1426 1427

		Set<?> wildcardSet();
S
sdeleuze 已提交
1428 1429 1430 1431

		List<String> list1();

		List<String> list2();
P
Phillip Webb 已提交
1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448
	}


	static class AssignmentBase<O, C, S> {

		public O o;

		public C c;

		public S s;

		public List<O> listo;

		public List<C> listc;

		public List<S> lists;

1449 1450
		public List<?> listAnon;

P
Phillip Webb 已提交
1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486
		public List<? extends O> listxo;

		public List<? extends C> listxc;

		public List<? extends S> listxs;

		public List<? super O> listso;

		public List<? super C> listsc;

		public List<? super S> listss;

		public O[] oarray;

		public C[] carray;

		public S[] sarray;

		public Collection<C> collectionc;

		public Collection<? extends C> collectionxc;

		public Map<? super Integer, List<String>> complexWildcard1;

		public MultiValueMap<Number, String> complexWildcard2;

		public Collection<? extends Collection<? extends CharSequence>> complexWildcard3;

		public List<List<String>> complexWildcard4;
	}


	static class Assignment extends AssignmentBase<Object, CharSequence, String> {
	}


1487
	interface TypedMethods extends Methods<String> {
P
Phillip Webb 已提交
1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515
	}


	static class Constructors<T> {

		public Constructors(List<CharSequence> p) {
		}

		public Constructors(Map<T, Long> p) {
		}
	}


	static class TypedConstructors extends Constructors<String> {

		public TypedConstructors(List<CharSequence> p) {
			super(p);
		}

		public TypedConstructors(Map<String, Long> p) {
			super(p);
		}
	}


	public interface MyInterfaceType<T> {
	}

S
Stephane Nicoll 已提交
1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532
	public class MyGenericInterfaceType<T> implements MyInterfaceType<T>, ResolvableTypeProvider {

		private final Class<T> type;

		public MyGenericInterfaceType(Class<T> type) {
			this.type = type;
		}

		@Override
		public ResolvableType getResolvableType() {
			if (this.type == null) {
				return null;
			}
			return ResolvableType.forClassWithGenerics(getClass(), this.type);
		}
	}

P
Phillip Webb 已提交
1533 1534 1535 1536

	public class MySimpleInterfaceType implements MyInterfaceType<String> {
	}

1537 1538 1539 1540 1541 1542
	public abstract class MySimpleInterfaceTypeWithImplementsRaw implements MyInterfaceType<String>, List {
	}

	public abstract class ExtendsMySimpleInterfaceTypeWithImplementsRaw extends MySimpleInterfaceTypeWithImplementsRaw {
	}

P
Phillip Webb 已提交
1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559

	public class MyCollectionInterfaceType implements MyInterfaceType<Collection<String>> {
	}


	public abstract class MySuperclassType<T> {
	}


	public class MySimpleSuperclassType extends MySuperclassType<String> {
	}


	public class MyCollectionSuperclassType extends MySuperclassType<Collection<String>> {
	}


1560
	interface Wildcard<T extends Number> extends List<T> {
P
Phillip Webb 已提交
1561 1562 1563
	}


1564
	interface RawExtendsWildcard extends Wildcard {
P
Phillip Webb 已提交
1565 1566 1567
	}


1568
	interface VariableNameSwitch<V, K> extends MultiValueMap<K, V> {
P
Phillip Webb 已提交
1569 1570 1571
	}


1572
	interface ListOfGenericArray extends List<List<String>[]> {
P
Phillip Webb 已提交
1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587
	}


	static class EnclosedInParameterizedType<T> {

		static class InnerRaw {
		}

		class InnerTyped<Y> {

			public T field;
		}
	}


1588
	static class TypedEnclosedInParameterizedType extends EnclosedInParameterizedType<Integer> {
P
Phillip Webb 已提交
1589 1590 1591 1592 1593

		class TypedInnerTyped extends InnerTyped<Long> {
		}
	}

1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611

	public interface IProvider<P> {
	}

	public interface IBase<BT extends IBase<BT>> {
	}

	public abstract class AbstractBase<BT extends IBase<BT>> implements IBase<BT> {
	}

	public class BaseImplementation extends AbstractBase<BaseImplementation> {
	}

	public class BaseProvider<BT extends IBase<BT>> implements IProvider<IBase<BT>> {

		public Collection<IBase<BT>> stuff;
	}

1612 1613 1614 1615 1616 1617

	public abstract class UnresolvedWithGenerics {

		Set<Integer> set;
	}

J
Juergen Hoeller 已提交
1618

1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653
	private static class ResolvableTypeAssert extends AbstractAssert<ResolvableTypeAssert, ResolvableType>{

		public ResolvableTypeAssert(ResolvableType actual) {
			super(actual, ResolvableTypeAssert.class);
		}

		public ResolvableTypeAssert isAssignableFrom(ResolvableType... types) {
			for (ResolvableType type : types) {
				if (!actual.isAssignableFrom(type)) {
					throw new AssertionError("Expecting " + decribe(actual) + " to be assignable from " + decribe(type));
				}
			}
			return this;
		}

		public ResolvableTypeAssert isNotAssignableFrom(ResolvableType... types) {
			for (ResolvableType type : types) {
				if (actual.isAssignableFrom(type)) {
					throw new AssertionError("Expecting " + decribe(actual) + " to not be assignable from " + decribe(type));
				}
			}
			return this;
		}

		private String decribe(ResolvableType type) {
			if (type == ResolvableType.NONE) {
				return "NONE";
			}
			if (type.getType().getClass().equals(Class.class)) {
				return type.toString();
			}
			return type.getType() + ":" + type;
		}
	}

P
Phillip Webb 已提交
1654
}