1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "method_handles.h"
18
19 #include "class_linker-inl.h"
20 #include "common_runtime_test.h"
21 #include "handle_scope-inl.h"
22 #include "jvalue-inl.h"
23 #include "mirror/method_type.h"
24 #include "mirror/object_array-inl.h"
25 #include "reflection.h"
26 #include "scoped_thread_state_change-inl.h"
27 #include "thread-current-inl.h"
28
29 namespace art {
30
31 namespace {
IsClassCastException(ObjPtr<mirror::Throwable> throwable)32 bool IsClassCastException(ObjPtr<mirror::Throwable> throwable)
33 REQUIRES_SHARED(Locks::mutator_lock_) {
34 return throwable->GetClass()->DescriptorEquals("Ljava/lang/ClassCastException;");
35 }
36
IsNullPointerException(ObjPtr<mirror::Throwable> throwable)37 bool IsNullPointerException(ObjPtr<mirror::Throwable> throwable)
38 REQUIRES_SHARED(Locks::mutator_lock_) {
39 return throwable->GetClass()->DescriptorEquals("Ljava/lang/NullPointerException;");
40 }
41
IsWrongMethodTypeException(ObjPtr<mirror::Throwable> throwable)42 bool IsWrongMethodTypeException(ObjPtr<mirror::Throwable> throwable)
43 REQUIRES_SHARED(Locks::mutator_lock_) {
44 return throwable->GetClass()->DescriptorEquals("Ljava/lang/invoke/WrongMethodTypeException;");
45 }
46
CreateVoidMethodType(Thread * self,Handle<mirror::Class> parameter_type)47 static mirror::MethodType* CreateVoidMethodType(Thread* self,
48 Handle<mirror::Class> parameter_type)
49 REQUIRES_SHARED(Locks::mutator_lock_) {
50 ClassLinker* cl = Runtime::Current()->GetClassLinker();
51 StackHandleScope<2> hs(self);
52 ObjPtr<mirror::Class> class_type = mirror::Class::GetJavaLangClass();
53 ObjPtr<mirror::Class> class_array_type = cl->FindArrayClass(self, &class_type);
54 auto parameter_types = hs.NewHandle(
55 mirror::ObjectArray<mirror::Class>::Alloc(self, class_array_type, 1));
56 parameter_types->Set(0, parameter_type.Get());
57 Handle<mirror::Class> void_class = hs.NewHandle(cl->FindPrimitiveClass('V'));
58 return mirror::MethodType::Create(self, void_class, parameter_types);
59 }
60
TryConversion(Thread * self,Handle<mirror::Class> from,Handle<mirror::Class> to,JValue * value)61 static bool TryConversion(Thread* self,
62 Handle<mirror::Class> from,
63 Handle<mirror::Class> to,
64 JValue* value)
65 REQUIRES_SHARED(Locks::mutator_lock_) {
66 StackHandleScope<2> hs(self);
67 Handle<mirror::MethodType> from_mt = hs.NewHandle(CreateVoidMethodType(self, from));
68 Handle<mirror::MethodType> to_mt = hs.NewHandle(CreateVoidMethodType(self, to));
69 return ConvertJValueCommon(from_mt, to_mt, from.Get(), to.Get(), value);
70 }
71 } // namespace
72
73 class MethodHandlesTest : public CommonRuntimeTest {};
74
75 //
76 // Primitive -> Primitive Conversions
77 //
78
TEST_F(MethodHandlesTest,SupportedPrimitiveWideningBI)79 TEST_F(MethodHandlesTest, SupportedPrimitiveWideningBI) {
80 ScopedObjectAccess soa(Thread::Current());
81 ClassLinker* cl = Runtime::Current()->GetClassLinker();
82 StackHandleScope<2> hs(soa.Self());
83 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('B'));
84 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('I'));
85 JValue value = JValue::FromPrimitive(static_cast<int8_t>(3));
86 ASSERT_TRUE(TryConversion(soa.Self(), from, to, &value));
87 ASSERT_EQ(3, value.GetI());
88 ASSERT_FALSE(soa.Self()->IsExceptionPending());
89 }
90
TEST_F(MethodHandlesTest,SupportedPrimitiveWideningCJ)91 TEST_F(MethodHandlesTest, SupportedPrimitiveWideningCJ) {
92 ScopedObjectAccess soa(Thread::Current());
93 ClassLinker* cl = Runtime::Current()->GetClassLinker();
94 StackHandleScope<2> hs(soa.Self());
95 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('C'));
96 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('J'));
97 uint16_t raw_value = 0x8000;
98 JValue value = JValue::FromPrimitive(raw_value);
99 ASSERT_TRUE(TryConversion(soa.Self(), from, to, &value));
100 ASSERT_FALSE(soa.Self()->IsExceptionPending());
101 ASSERT_EQ(static_cast<int64_t>(raw_value), value.GetJ());
102 }
103
TEST_F(MethodHandlesTest,SupportedPrimitiveWideningIF)104 TEST_F(MethodHandlesTest, SupportedPrimitiveWideningIF) {
105 ScopedObjectAccess soa(Thread::Current());
106 ClassLinker* cl = Runtime::Current()->GetClassLinker();
107 StackHandleScope<2> hs(soa.Self());
108 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('I'));
109 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('F'));
110 JValue value = JValue::FromPrimitive(-16);
111 ASSERT_TRUE(TryConversion(soa.Self(), from, to, &value));
112 ASSERT_FALSE(soa.Self()->IsExceptionPending());
113 ASSERT_FLOAT_EQ(-16.0f, value.GetF());
114 }
115
TEST_F(MethodHandlesTest,UnsupportedPrimitiveWideningBC)116 TEST_F(MethodHandlesTest, UnsupportedPrimitiveWideningBC) {
117 ScopedObjectAccess soa(Thread::Current());
118 ClassLinker* cl = Runtime::Current()->GetClassLinker();
119 StackHandleScope<2> hs(soa.Self());
120 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('B'));
121 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('C'));
122 JValue value;
123 value.SetB(0);
124 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value));
125 ASSERT_TRUE(soa.Self()->IsExceptionPending());
126 ASSERT_TRUE(IsWrongMethodTypeException(soa.Self()->GetException()));
127 soa.Self()->ClearException();
128 }
129
TEST_F(MethodHandlesTest,UnsupportedPrimitiveWideningSC)130 TEST_F(MethodHandlesTest, UnsupportedPrimitiveWideningSC) {
131 ScopedObjectAccess soa(Thread::Current());
132 ClassLinker* cl = Runtime::Current()->GetClassLinker();
133 StackHandleScope<2> hs(soa.Self());
134 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('S'));
135 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('C'));
136 JValue value;
137 value.SetS(0x1234);
138 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value));
139 ASSERT_TRUE(soa.Self()->IsExceptionPending());
140 ASSERT_TRUE(IsWrongMethodTypeException(soa.Self()->GetException()));
141 soa.Self()->ClearException();
142 }
143
TEST_F(MethodHandlesTest,UnsupportedPrimitiveWideningDJ)144 TEST_F(MethodHandlesTest, UnsupportedPrimitiveWideningDJ) {
145 ScopedObjectAccess soa(Thread::Current());
146 ClassLinker* cl = Runtime::Current()->GetClassLinker();
147 StackHandleScope<2> hs(soa.Self());
148 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('D'));
149 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('J'));
150 JValue value;
151 value.SetD(1e72);
152 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value));
153 ASSERT_TRUE(soa.Self()->IsExceptionPending());
154 ASSERT_TRUE(IsWrongMethodTypeException(soa.Self()->GetException()));
155 soa.Self()->ClearException();
156 }
157
TEST_F(MethodHandlesTest,UnsupportedPrimitiveWideningZI)158 TEST_F(MethodHandlesTest, UnsupportedPrimitiveWideningZI) {
159 ScopedObjectAccess soa(Thread::Current());
160 ClassLinker* cl = Runtime::Current()->GetClassLinker();
161 StackHandleScope<2> hs(soa.Self());
162 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('Z'));
163 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('I'));
164 JValue value;
165 value.SetZ(true);
166 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value));
167 ASSERT_TRUE(soa.Self()->IsExceptionPending());
168 ASSERT_TRUE(IsWrongMethodTypeException(soa.Self()->GetException()));
169 soa.Self()->ClearException();
170 }
171
172 //
173 // Reference -> Reference Conversions
174 //
175
TEST_F(MethodHandlesTest,SupportedReferenceCast)176 TEST_F(MethodHandlesTest, SupportedReferenceCast) {
177 ScopedObjectAccess soa(Thread::Current());
178 ClassLinker* cl = Runtime::Current()->GetClassLinker();
179 StackHandleScope<3> hs(soa.Self());
180 static const int32_t kInitialValue = 101;
181 JValue value = JValue::FromPrimitive(kInitialValue);
182 Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr());
183 Handle<mirror::Class> from = hs.NewHandle(boxed_value->GetClass());
184 Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Number;"));
185 value.SetL(boxed_value.Get());
186 ASSERT_TRUE(TryConversion(soa.Self(), from, to, &value));
187 ASSERT_FALSE(soa.Self()->IsExceptionPending());
188 JValue unboxed_value;
189 ASSERT_TRUE(UnboxPrimitiveForResult(value.GetL(), cl->FindPrimitiveClass('I'), &unboxed_value));
190 ASSERT_EQ(kInitialValue, unboxed_value.GetI());
191 }
192
TEST_F(MethodHandlesTest,UnsupportedReferenceCast)193 TEST_F(MethodHandlesTest, UnsupportedReferenceCast) {
194 ScopedObjectAccess soa(Thread::Current());
195 ClassLinker* cl = Runtime::Current()->GetClassLinker();
196 StackHandleScope<3> hs(soa.Self());
197 JValue value = JValue::FromPrimitive(3.733e2);
198 Handle<mirror::Object> boxed_value =
199 hs.NewHandle(BoxPrimitive(Primitive::kPrimDouble, value).Ptr());
200 Handle<mirror::Class> from = hs.NewHandle(boxed_value->GetClass());
201 Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;"));
202 value.SetL(boxed_value.Get());
203 ASSERT_FALSE(soa.Self()->IsExceptionPending());
204 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value));
205 ASSERT_TRUE(soa.Self()->IsExceptionPending());
206 ASSERT_TRUE(IsClassCastException(soa.Self()->GetException()));
207 soa.Self()->ClearException();
208 }
209
210 //
211 // Primitive -> Reference Conversions
212 //
213
TEST_F(MethodHandlesTest,SupportedPrimitiveConversionPrimitiveToBoxed)214 TEST_F(MethodHandlesTest, SupportedPrimitiveConversionPrimitiveToBoxed) {
215 ScopedObjectAccess soa(Thread::Current());
216 ClassLinker* cl = Runtime::Current()->GetClassLinker();
217 StackHandleScope<2> hs(soa.Self());
218 const int32_t kInitialValue = 1;
219 JValue value = JValue::FromPrimitive(kInitialValue);
220 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('I'));
221 Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;"));
222 ASSERT_TRUE(TryConversion(soa.Self(), from, to, &value));
223 ASSERT_FALSE(soa.Self()->IsExceptionPending());
224 JValue unboxed_to_value;
225 ASSERT_TRUE(UnboxPrimitiveForResult(value.GetL(), from.Get(), &unboxed_to_value));
226 ASSERT_EQ(kInitialValue, unboxed_to_value.GetI());
227 }
228
TEST_F(MethodHandlesTest,SupportedPrimitiveConversionPrimitiveToBoxedSuper)229 TEST_F(MethodHandlesTest, SupportedPrimitiveConversionPrimitiveToBoxedSuper) {
230 ScopedObjectAccess soa(Thread::Current());
231 ClassLinker* cl = Runtime::Current()->GetClassLinker();
232 StackHandleScope<2> hs(soa.Self());
233 const int32_t kInitialValue = 1;
234 JValue value = JValue::FromPrimitive(kInitialValue);
235 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('I'));
236 Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Number;"));
237 ASSERT_TRUE(TryConversion(soa.Self(), from, to, &value));
238 ASSERT_FALSE(soa.Self()->IsExceptionPending());
239 JValue unboxed_to_value;
240 ASSERT_TRUE(UnboxPrimitiveForResult(value.GetL(), from.Get(), &unboxed_to_value));
241 ASSERT_EQ(kInitialValue, unboxed_to_value.GetI());
242 }
243
TEST_F(MethodHandlesTest,UnsupportedPrimitiveConversionNotBoxable)244 TEST_F(MethodHandlesTest, UnsupportedPrimitiveConversionNotBoxable) {
245 ScopedObjectAccess soa(Thread::Current());
246 ClassLinker* cl = Runtime::Current()->GetClassLinker();
247 StackHandleScope<2> hs(soa.Self());
248 const int32_t kInitialValue = 1;
249 JValue value = JValue::FromPrimitive(kInitialValue);
250 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('I'));
251 Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Runtime;"));
252 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value));
253 ASSERT_TRUE(soa.Self()->IsExceptionPending());
254 ASSERT_TRUE(IsWrongMethodTypeException(soa.Self()->GetException()));
255 soa.Self()->ClearException();
256 }
257
TEST_F(MethodHandlesTest,UnsupportedPrimitiveConversionPrimitiveToBoxedWider)258 TEST_F(MethodHandlesTest, UnsupportedPrimitiveConversionPrimitiveToBoxedWider) {
259 ScopedObjectAccess soa(Thread::Current());
260 ClassLinker* cl = Runtime::Current()->GetClassLinker();
261 StackHandleScope<2> hs(soa.Self());
262 const int32_t kInitialValue = 1;
263 JValue value = JValue::FromPrimitive(kInitialValue);
264 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('I'));
265 Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Long;"));
266 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value));
267 ASSERT_TRUE(soa.Self()->IsExceptionPending());
268 ASSERT_TRUE(IsWrongMethodTypeException(soa.Self()->GetException()));
269 soa.Self()->ClearException();
270 }
271
TEST_F(MethodHandlesTest,UnsupportedPrimitiveConversionPrimitiveToBoxedNarrower)272 TEST_F(MethodHandlesTest, UnsupportedPrimitiveConversionPrimitiveToBoxedNarrower) {
273 ScopedObjectAccess soa(Thread::Current());
274 ClassLinker* cl = Runtime::Current()->GetClassLinker();
275 StackHandleScope<2> hs(soa.Self());
276 const int32_t kInitialValue = 1;
277 JValue value = JValue::FromPrimitive(kInitialValue);
278 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('I'));
279 Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Byte;"));
280 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value));
281 ASSERT_TRUE(soa.Self()->IsExceptionPending());
282 ASSERT_TRUE(IsWrongMethodTypeException(soa.Self()->GetException()));
283 soa.Self()->ClearException();
284 }
285
286 //
287 // Reference -> Primitive Conversions
288 //
289
TEST_F(MethodHandlesTest,SupportedBoxedToPrimitiveConversion)290 TEST_F(MethodHandlesTest, SupportedBoxedToPrimitiveConversion) {
291 ScopedObjectAccess soa(Thread::Current());
292 ClassLinker* cl = Runtime::Current()->GetClassLinker();
293 StackHandleScope<3> hs(soa.Self());
294 const int32_t kInitialValue = 101;
295 JValue value = JValue::FromPrimitive(kInitialValue);
296 Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr());
297 Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;"));
298 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('I'));
299 value.SetL(boxed_value.Get());
300 ASSERT_TRUE(TryConversion(soa.Self(), from, to, &value));
301 ASSERT_FALSE(soa.Self()->IsExceptionPending());
302 ASSERT_EQ(kInitialValue, value.GetI());
303 }
304
TEST_F(MethodHandlesTest,SupportedBoxedToWiderPrimitiveConversion)305 TEST_F(MethodHandlesTest, SupportedBoxedToWiderPrimitiveConversion) {
306 ScopedObjectAccess soa(Thread::Current());
307 ClassLinker* cl = Runtime::Current()->GetClassLinker();
308 StackHandleScope<3> hs(soa.Self());
309 static const int32_t kInitialValue = 101;
310 JValue value = JValue::FromPrimitive(kInitialValue);
311 Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr());
312 Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;"));
313 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('J'));
314 value.SetL(boxed_value.Get());
315 ASSERT_TRUE(TryConversion(soa.Self(), from, to, &value));
316 ASSERT_EQ(kInitialValue, value.GetJ());
317 }
318
TEST_F(MethodHandlesTest,UnsupportedNullBoxedToPrimitiveConversion)319 TEST_F(MethodHandlesTest, UnsupportedNullBoxedToPrimitiveConversion) {
320 ScopedObjectAccess soa(Thread::Current());
321 ClassLinker* cl = Runtime::Current()->GetClassLinker();
322 StackHandleScope<3> hs(soa.Self());
323 JValue value = JValue::FromPrimitive(101);
324 ScopedNullHandle<mirror::Object> boxed_value;
325 Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;"));
326 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('I'));
327 value.SetL(boxed_value.Get());
328 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value));
329 ASSERT_TRUE(soa.Self()->IsExceptionPending());
330 ASSERT_TRUE(IsNullPointerException(soa.Self()->GetException()));
331 soa.Self()->ClearException();
332 }
333
TEST_F(MethodHandlesTest,UnsupportedNotBoxReferenceToPrimitiveConversion)334 TEST_F(MethodHandlesTest, UnsupportedNotBoxReferenceToPrimitiveConversion) {
335 ScopedObjectAccess soa(Thread::Current());
336 ClassLinker* cl = Runtime::Current()->GetClassLinker();
337 StackHandleScope<2> hs(soa.Self());
338 Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Class;"));
339 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('I'));
340 // Set value to be converted as some non-primitive type.
341 JValue value;
342 value.SetL(cl->FindPrimitiveClass('V'));
343 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value));
344 ASSERT_TRUE(soa.Self()->IsExceptionPending());
345 ASSERT_TRUE(IsWrongMethodTypeException(soa.Self()->GetException()));
346 soa.Self()->ClearException();
347 }
348
TEST_F(MethodHandlesTest,UnsupportedBoxedToNarrowerPrimitiveConversionNoCast)349 TEST_F(MethodHandlesTest, UnsupportedBoxedToNarrowerPrimitiveConversionNoCast) {
350 ScopedObjectAccess soa(Thread::Current());
351 ClassLinker* cl = Runtime::Current()->GetClassLinker();
352 StackHandleScope<3> hs(soa.Self());
353 static const int32_t kInitialValue = 101;
354 JValue value = JValue::FromPrimitive(kInitialValue);
355 Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr());
356 Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;"));
357 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('S'));
358 value.SetL(boxed_value.Get());
359 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value));
360 ASSERT_TRUE(soa.Self()->IsExceptionPending());
361 ASSERT_TRUE(IsWrongMethodTypeException(soa.Self()->GetException()));
362 soa.Self()->ClearException();
363 }
364
TEST_F(MethodHandlesTest,UnsupportedBoxedToNarrowerPrimitiveConversionWithCast)365 TEST_F(MethodHandlesTest, UnsupportedBoxedToNarrowerPrimitiveConversionWithCast) {
366 ScopedObjectAccess soa(Thread::Current());
367 ClassLinker* cl = Runtime::Current()->GetClassLinker();
368 StackHandleScope<3> hs(soa.Self());
369 static const double kInitialValue = 1e77;
370 JValue value = JValue::FromPrimitive(kInitialValue);
371 Handle<mirror::Object> boxed_value =
372 hs.NewHandle(BoxPrimitive(Primitive::kPrimDouble, value).Ptr());
373 Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Number;"));
374 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('F'));
375 value.SetL(boxed_value.Get());
376 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value));
377 ASSERT_TRUE(soa.Self()->IsExceptionPending());
378 ASSERT_TRUE(IsClassCastException(soa.Self()->GetException()));
379 soa.Self()->ClearException();
380 }
381
382 } // namespace art
383