View Javadoc
1   /*
2    * MIT License
3    * Copyright (c) 2006-2025 JMockit developers
4    * See LICENSE file for full license text.
5    */
6   package mockit.internal.reflection;
7   
8   import static org.junit.jupiter.api.Assertions.assertArrayEquals;
9   import static org.junit.jupiter.api.Assertions.assertEquals;
10  import static org.junit.jupiter.api.Assertions.assertFalse;
11  import static org.junit.jupiter.api.Assertions.assertNotNull;
12  import static org.junit.jupiter.api.Assertions.assertThrows;
13  import static org.junit.jupiter.api.Assertions.assertTrue;
14  
15  import java.lang.reflect.Method;
16  
17  import mockit.Invocation;
18  
19  import org.junit.jupiter.api.Test;
20  
21  final class ParameterReflectionTest {
22  
23      @Test
24      void getParameterTypesDescriptionWithNoParams() {
25          String desc = ParameterReflection.getParameterTypesDescription(new Class<?>[0]);
26          assertEquals("()", desc);
27      }
28  
29      @Test
30      void getParameterTypesDescriptionWithSingleParam() {
31          String desc = ParameterReflection.getParameterTypesDescription(new Class<?>[] { String.class });
32          assertEquals("(String)", desc);
33      }
34  
35      @Test
36      void getParameterTypesDescriptionWithMultipleParams() {
37          String desc = ParameterReflection.getParameterTypesDescription(new Class<?>[] { int.class, String.class });
38          assertEquals("(int, String)", desc);
39      }
40  
41      @Test
42      void getArgumentTypesFromArgumentValuesWithNoArgs() {
43          Class<?>[] types = ParameterReflection.getArgumentTypesFromArgumentValues();
44          assertArrayEquals(ParameterReflection.NO_PARAMETERS, types);
45      }
46  
47      @Test
48      void getArgumentTypesFromArgumentValuesWithClassArg() {
49          // When arg is a Class, it represents the type (and the value becomes null)
50          Object[] args = { String.class };
51          Class<?>[] types = ParameterReflection.getArgumentTypesFromArgumentValues(args);
52          assertEquals(1, types.length);
53          assertEquals(String.class, types[0]);
54          // arg should have been set to null
55          assertArrayEquals(new Object[] { null }, args);
56      }
57  
58      @Test
59      void getArgumentTypesFromArgumentValuesWithObjectArg() {
60          Class<?>[] types = ParameterReflection.getArgumentTypesFromArgumentValues("hello");
61          assertEquals(1, types.length);
62          assertEquals(String.class, types[0]);
63      }
64  
65      @Test
66      void getArgumentTypesFromArgumentValuesThrowsForNullArg() {
67          assertThrows(IllegalArgumentException.class,
68                  () -> ParameterReflection.getArgumentTypesFromArgumentValues(new Object[] { null }));
69      }
70  
71      @Test
72      void argumentsWithExtraFirstValue() {
73          Object[] result = ParameterReflection.argumentsWithExtraFirstValue(new Object[] { "b", "c" }, "a");
74          assertArrayEquals(new Object[] { "a", "b", "c" }, result);
75      }
76  
77      @Test
78      void hasMoreSpecificTypesReturnsTrueWhenMoreSpecific() {
79          // String is more specific than Object
80          boolean result = ParameterReflection.hasMoreSpecificTypes(new Class<?>[] { String.class },
81                  new Class<?>[] { Object.class });
82          assertTrue(result);
83      }
84  
85      @Test
86      void hasMoreSpecificTypesReturnsFalseWhenSame() {
87          boolean result = ParameterReflection.hasMoreSpecificTypes(new Class<?>[] { String.class },
88                  new Class<?>[] { String.class });
89          assertFalse(result);
90      }
91  
92      @Test
93      void hasMoreSpecificTypesWithPrimitiveTypes() {
94          // int wrapped to Integer, same as Integer - not more specific
95          boolean result = ParameterReflection.hasMoreSpecificTypes(new Class<?>[] { int.class },
96                  new Class<?>[] { int.class });
97          assertFalse(result);
98      }
99  
100     @Test
101     void acceptsArgumentTypesWithExactMatch() {
102         boolean result = ParameterReflection.acceptsArgumentTypes(new Class<?>[] { String.class },
103                 new Class<?>[] { String.class }, 0);
104         assertTrue(result);
105     }
106 
107     @Test
108     void acceptsArgumentTypesWithAutoboxing() {
109         boolean result = ParameterReflection.acceptsArgumentTypes(new Class<?>[] { int.class },
110                 new Class<?>[] { Integer.class }, 0);
111         assertTrue(result);
112     }
113 
114     @Test
115     void acceptsArgumentTypesWithSubclass() {
116         // StringBuilder is assignable from CharSequence
117         boolean result = ParameterReflection.acceptsArgumentTypes(new Class<?>[] { CharSequence.class },
118                 new Class<?>[] { String.class }, 0);
119         assertTrue(result);
120     }
121 
122     @Test
123     void acceptsArgumentTypesReturnsFalseForIncompatible() {
124         boolean result = ParameterReflection.acceptsArgumentTypes(new Class<?>[] { String.class },
125                 new Class<?>[] { Integer.class }, 0);
126         assertFalse(result);
127     }
128 
129     @Test
130     void isSameTypeIgnoringAutoBoxingWithSameType() {
131         assertTrue(ParameterReflection.isSameTypeIgnoringAutoBoxing(String.class, String.class));
132     }
133 
134     @Test
135     void isSameTypeIgnoringAutoBoxingWithPrimitiveAndWrapper() {
136         assertTrue(ParameterReflection.isSameTypeIgnoringAutoBoxing(int.class, Integer.class));
137         assertTrue(ParameterReflection.isSameTypeIgnoringAutoBoxing(Integer.class, int.class));
138     }
139 
140     @Test
141     void isSameTypeIgnoringAutoBoxingWithDifferentTypes() {
142         assertFalse(ParameterReflection.isSameTypeIgnoringAutoBoxing(String.class, Integer.class));
143     }
144 
145     @Test
146     void indexOfFirstRealParameterWithInvocationFirst() {
147         int result = ParameterReflection.indexOfFirstRealParameter(new Class<?>[] { Invocation.class, String.class },
148                 new Class<?>[] { String.class });
149         assertEquals(1, result);
150     }
151 
152     @Test
153     void indexOfFirstRealParameterWithNoExtra() {
154         int result = ParameterReflection.indexOfFirstRealParameter(new Class<?>[] { String.class },
155                 new Class<?>[] { String.class });
156         assertEquals(0, result);
157     }
158 
159     @Test
160     void indexOfFirstRealParameterWithWrongExtraType() {
161         // Extra param but not Invocation -> -1
162         int result = ParameterReflection.indexOfFirstRealParameter(new Class<?>[] { String.class, Integer.class },
163                 new Class<?>[] { Integer.class });
164         assertEquals(-1, result);
165     }
166 
167     @Test
168     void indexOfFirstRealParameterWithTooManyExtras() {
169         // 2 extra params -> -1
170         int result = ParameterReflection.indexOfFirstRealParameter(
171                 new Class<?>[] { Invocation.class, String.class, Integer.class }, new Class<?>[] { Integer.class });
172         assertEquals(-1, result);
173     }
174 
175     @Test
176     void matchesParameterTypesWithExactMatch() {
177         assertTrue(ParameterReflection.matchesParameterTypes(new Class<?>[] { String.class },
178                 new Class<?>[] { String.class }, 0));
179     }
180 
181     @Test
182     void matchesParameterTypesReturnsFalseForMismatch() {
183         assertFalse(ParameterReflection.matchesParameterTypes(new Class<?>[] { String.class },
184                 new Class<?>[] { Integer.class }, 0));
185     }
186 
187     @Test
188     void getParameterCountReturnsCorrectCount() throws NoSuchMethodException {
189         Method method = String.class.getMethod("substring", int.class, int.class);
190         int count = ParameterReflection.getParameterCount(method);
191         assertEquals(2, count);
192     }
193 
194     @Test
195     void noParametersConstantIsEmpty() {
196         assertNotNull(ParameterReflection.NO_PARAMETERS);
197         assertEquals(0, ParameterReflection.NO_PARAMETERS.length);
198     }
199 }