The open source OpenXR runtime
1// Project Dependencies
2#include <jnipp.h>
3
4// Standard Dependencies
5#include <cmath>
6
7// Local Dependencies
8#include "testing.h"
9
10/*
11 jni::Vm Tests
12 */
13
14
15TEST(Vm_detectsJreInstall)
16{
17 try
18 {
19 jni::Vm vm;
20 }
21 catch (jni::InitializationException&)
22 {
23 ASSERT(0);
24 return;
25 }
26
27 ASSERT(1);
28}
29
30TEST(Vm_notAllowedMultipleVms)
31{
32 try
33 {
34 jni::Vm firstVm;
35 jni::Vm secondVm; // Throws an exception.
36 }
37 catch (jni::InitializationException&)
38 {
39 ASSERT(1);
40 return;
41 }
42
43 ASSERT(0);
44}
45
46/*
47 jni::Class Tests
48 */
49
50
51TEST(Class_findByName_success)
52{
53 jni::Class cls("java/lang/String");
54
55 ASSERT(!cls.isNull());
56}
57
58TEST(Class_findByName_failure)
59{
60 try
61 {
62 jni::Class cls("does/not/Exist");
63 }
64 catch (jni::NameResolutionException&)
65 {
66 ASSERT(1);
67 return;
68 }
69
70 ASSERT(0);
71}
72
73TEST(Class_getName)
74{
75 jni::Class cls("java/lang/String");
76
77 ASSERT(cls.getName() == "java.lang.String");
78}
79
80TEST(Class_getParent)
81{
82 jni::Class parent = jni::Class("java/lang/Integer").getParent();
83
84 ASSERT(parent.getName() == "java.lang.Number");
85}
86
87TEST(Class_newInstance)
88{
89 jni::Class Integer("java/lang/Integer");
90 jni::method_t constructor = Integer.getConstructor("(Ljava/lang/String;)V");
91 jni::Object i = Integer.newInstance(constructor, "123");
92 jni::Object str = jni::Class("java/lang/String").newInstance();
93
94 ASSERT(!i.isNull());
95 ASSERT(!str.isNull());
96}
97
98TEST(Class_newInstance_withArgs)
99{
100 jni::Object str1 = jni::Class("java/lang/String").newInstance("Testing...");
101 jni::Object str2 = jni::Class("java/lang/String").newInstance(L"Testing...");
102
103 ASSERT(!str1.isNull());
104 ASSERT(!str2.isNull());
105}
106
107TEST(Class_getStaticField)
108{
109 jni::field_t field = jni::Class("java/lang/Integer").getStaticField("MAX_VALUE", "I");
110
111 ASSERT(field);
112}
113
114TEST(Class_getMethod)
115{
116 jni::method_t method1 = jni::Class("java/lang/Integer").getMethod("intValue", "()I");
117 jni::method_t method2 = jni::Class("java/lang/Integer").getMethod("intValue()I");
118
119 ASSERT(method1);
120 ASSERT(method2);
121}
122
123TEST(Class_getStaticMethod)
124{
125 jni::method_t method = jni::Class("java/lang/Integer").getStaticMethod("compare", "(II)I");
126
127 ASSERT(method);
128}
129
130TEST(Class_call)
131{
132 jni::Class Integer("java/lang/Math");
133
134 double x = Integer.call<double>("random");
135
136 ASSERT(x >= 0.0);
137 ASSERT(x < 1.0);
138}
139
140TEST(Class_get_staticField)
141{
142 jni::Class Integer("java/lang/Integer");
143 jni::field_t field = Integer.getStaticField("SIZE", "I");
144
145 ASSERT(Integer.get<int>(field) == 32);
146}
147
148TEST(Class_get_staticField_byName)
149{
150 jni::Class Integer("java/lang/Integer");
151 jni::Class Character("java/lang/Character");
152 jni::Class Short("java/lang/Short");
153 jni::Class Long("java/lang/Long");
154 jni::Class Float("java/lang/Float");
155 jni::Class Double("java/lang/Double");
156
157 ASSERT(Short.get<short>("MAX_VALUE") == short(0x7FFF));
158 ASSERT(Character.get<wchar_t>("MAX_VALUE") == L'\xFFFF')
159 ASSERT(Integer.get<int>("MAX_VALUE") == int(0x7FFFFFFF));
160 ASSERT(Long.get<long long>("MAX_VALUE") == (long long) (0x7FFFFFFFFFFFFFFF));
161 ASSERT(std::isnan(Float.get<float>("NaN")));
162 ASSERT(std::isnan(Double.get<double>("NaN")));
163}
164
165TEST(Class_getConstructor)
166{
167 jni::Class Integer("java/lang/Integer");
168 jni::method_t constructor = Integer.getConstructor("(Ljava/lang/String;)V");
169
170 ASSERT(constructor);
171}
172
173TEST(Class_call_staticMethod)
174{
175 jni::Class Integer("java/lang/Integer");
176 jni::method_t method = Integer.getStaticMethod("parseInt", "(Ljava/lang/String;)I");
177
178 int i = Integer.call<int>(method, "1000");
179
180 ASSERT(i == 1000);
181}
182
183TEST(Class_call_staticMethod_byName)
184{
185 int i = jni::Class("java/lang/Integer").call<int>("parseInt", "1000");
186 bool b = jni::Class("java/lang/Boolean").call<bool>("parseBoolean", "true");
187 wchar_t c = jni::Class("java/lang/Character").call<wchar_t>("toLowerCase", L'X');
188 short s = jni::Class("java/lang/Short").call<short>("parseShort", "1000");
189 long long l = jni::Class("java/lang/Long").call<long long>("parseLong", "1000");
190 float f = jni::Class("java/lang/Float").call<float>("parseFloat", "123.0");
191 double d = jni::Class("java/lang/Double").call<double>("parseDouble", "123.0");
192
193 ASSERT(i == 1000);
194 ASSERT(b == true);
195 ASSERT(c == L'x');
196 ASSERT(s == 1000);
197 ASSERT(l == 1000);
198 ASSERT(f == 123.0); // Warning: floating point comparison.
199 ASSERT(d == 123.0); // Warning: floating point comparison.
200}
201
202/*
203 jni::Object Tests
204 */
205
206// Must run before loading JVM
207TEST(Object_noDestructorException)
208{
209 jni::Object o;
210}
211
212TEST(Object_defaultConstructor_isNull)
213{
214 jni::Object o;
215
216 ASSERT(o.isNull());
217}
218
219TEST(Object_copyConstructorIsSameObject)
220{
221 jni::Object a = jni::Class("java/lang/String").newInstance();
222 jni::Object b = a;
223
224 ASSERT(a == b);
225}
226
227TEST(Object_moveConstructor)
228{
229 jni::Object a = jni::Class("java/lang/String").newInstance();
230 jni::Object b = std::move(a);
231
232 ASSERT(a.isNull());
233 ASSERT(!b.isNull());
234}
235
236TEST(Object_copyAssignmentOperator)
237{
238 jni::Object a = jni::Class("java/lang/String").newInstance();
239 jni::Object b = jni::Class("java/lang/Integer").newInstance(0);
240
241 a = b;
242
243 ASSERT(a == b);
244}
245
246TEST(Object_moveAssignmentOperator)
247{
248 jni::Object a = jni::Class("java/lang/String").newInstance();
249 jni::Object b = jni::Class("java/lang/Integer").newInstance(0);
250
251 a = std::move(b);
252
253 ASSERT(!a.isNull());
254 ASSERT(b.isNull());
255}
256
257TEST(Object_nullary_construct_from_signature)
258{
259 jni::Class String("java/lang/String");
260 jni::method_t init = String.getMethod("<init>", "()V");
261 jni::Object i = String.newInstance(init);
262 ASSERT(!i.isNull());
263 jni::internal::ArgArray<> a;
264}
265
266TEST(Object_call)
267{
268 jni::Class Integer("java/lang/Integer");
269 jni::method_t intValue = Integer.getMethod("intValue", "()I");
270 jni::Object i = Integer.newInstance(100);
271
272 ASSERT(i.call<int>(intValue) == 100);
273}
274
275TEST(Object_call_byName)
276{
277 jni::Object i = jni::Class("java/lang/Integer").newInstance(100);
278 jni::Object b = jni::Class("java/lang/Boolean").newInstance(true);
279 jni::Object s = jni::Class("java/lang/Short").newInstance(short(100));
280 jni::Object l = jni::Class("java/lang/Long").newInstance(100LL);
281 jni::Object f = jni::Class("java/lang/Float").newInstance(100.0f);
282 jni::Object d = jni::Class("java/lang/Double").newInstance(100.0);
283
284 ASSERT(i.call<int>("intValue") == 100);
285 ASSERT(s.call<short>("shortValue") == 100);
286 ASSERT(b.call<bool>("booleanValue") == true);
287 ASSERT(l.call<long long>("longValue") == 100LL);
288 ASSERT(f.call<float>("floatValue") == 100.0f); // Warning: Floating point comparison.
289 ASSERT(d.call<double>("doubleValue") == 100.0); // Warning: Floating point comparison.
290 ASSERT(i.call<std::wstring>("toString") == L"100");
291 ASSERT(i.call<std::string>("toString") == "100");
292}
293
294TEST(Object_call_withArgs)
295{
296 jni::Class String("java/lang/String");
297 jni::method_t charAt = String.getMethod("charAt", "(I)C");
298 jni::Object str = String.newInstance("Testing");
299
300 ASSERT(str.call<wchar_t>(charAt, 1) == L'e');
301}
302
303TEST(Object_call_byNameWithArgs)
304{
305 jni::Object str = jni::Class("java/lang/String").newInstance("Testing");
306 jni::Object str2 = jni::Class("java/lang/String").newInstance(L"Testing");
307
308 ASSERT(str.call<wchar_t>("charAt", 1) == L'e');
309 ASSERT(str2.call<wchar_t>("charAt", 1) == L'e');
310}
311
312TEST(Object_call_returningArray) {
313 jni::Object str = jni::Class("java/lang/String").newInstance("Testing");
314
315 {
316 auto getBytes =
317 jni::Class("java/lang/String").getMethod("getBytes", "()[B");
318 auto bytes = str.call<jni::Array<jni::byte_t>>(getBytes);
319 ASSERT(bytes.getLength() == 7);
320 }
321 {
322 auto bytes = str.call<jni::Array<jni::byte_t>>("getBytes");
323 ASSERT(bytes.getLength() == 7);
324 }
325}
326
327TEST(Object_makeLocalReference)
328{
329 jni::Object str = jni::Class("java/lang/String").newInstance("Testing");
330
331 jni::jobject local = str.makeLocalReference();
332 ASSERT(local != nullptr);
333 ASSERT(local != str.getHandle());
334
335 jni::Object fromLocal(local, jni::Object::DeleteLocalInput);
336 ASSERT(!fromLocal.isNull());
337 ASSERT(str == fromLocal);
338}
339
340/*
341 jni::Enum Tests
342 */
343
344
345TEST(Enum_get)
346{
347 jni::Class Thread("java/lang/Thread");
348 jni::Enum State("java/lang/Thread$State");
349 jni::method_t currentThread = Thread.getStaticMethod("currentThread", "()Ljava/lang/Thread;");
350 jni::method_t getState = Thread.getMethod("getState", "()Ljava/lang/Thread$State;");
351
352 jni::Object thread = Thread.call<jni::Object>(currentThread);
353 jni::Object state = thread.call<jni::Object>(getState);
354
355 ASSERT(state == State.get("RUNNABLE"));
356}
357
358/*
359 jni::Array Tests
360 */
361
362TEST(Array_defaultConstructor)
363{
364 jni::Array<int> a;
365
366 ASSERT(a.getLength() == 0);
367 ASSERT(a.isNull());
368}
369
370TEST(Array_constructor)
371{
372 jni::Array<int> a(10);
373
374 ASSERT(a.getLength() == 10);
375 ASSERT(!a.isNull());
376}
377
378TEST(Array_constructor_eachType)
379{
380 jni::Array<bool> b(10);
381 jni::Array<wchar_t> c(10);
382 jni::Array<short> s(10);
383 jni::Array<int> i(10);
384 jni::Array<long long> l(10);
385 jni::Array<float> f(10);
386 jni::Array<double> d(10);
387 jni::Array<std::string> str(10);
388 jni::Array<std::wstring> wstr(10);
389 jni::Array<jni::Object> obj(10);
390 jni::Array<jni::Object> obj2(10, jni::Class("java/lang/Integer"));
391
392 jni::Object* objs[] = { &b, &c, &s, &i, &l, &f, &d, &str, &wstr, &obj, &obj2 };
393
394 for (auto o : objs)
395 ASSERT(!o->isNull());
396}
397
398TEST(Array_constructor_withType)
399{
400 jni::Array<jni::Object> a(10, jni::Class("java/lang/Integer"));
401
402 ASSERT(a.getLength() == 10);
403 ASSERT(!a.isNull());
404}
405
406TEST(Array_copyConstructor)
407{
408 jni::Array<int> a(10);
409 jni::Array<int> b = a;
410
411 ASSERT(a == b);
412}
413
414TEST(Array_moveConstructor)
415{
416 jni::Array<int> a(10);
417 jni::Array<int> b = std::move(a);
418
419 ASSERT(a.isNull());
420 ASSERT(!b.isNull());
421}
422
423TEST(Array_copyAssignmentOperator)
424{
425 jni::Array<int> a(10);
426 jni::Array<int> b(11);
427
428 a = b;
429
430 ASSERT(a == b);
431}
432
433TEST(Array_moveAssignmentOperator)
434{
435 jni::Array<int> a(10);
436 jni::Array<int> b(11);
437
438 a = std::move(b);
439
440 ASSERT(!a.isNull());
441 ASSERT(b.isNull());
442}
443
444TEST(Array_getElement_defaultValue)
445{
446 jni::Array<int> a(10);
447 jni::Array<std::string> s(10);
448
449 ASSERT(a.getElement(0) == 0);
450 ASSERT(s.getElement(0).length() == 0);
451}
452
453TEST(Array_getElement_indexException)
454{
455 jni::Array<int> a(10);
456
457 try
458 {
459 int result = a.getElement(1000);
460 ASSERT(0);
461 }
462 catch (jni::Exception&)
463 {
464 ASSERT(1);
465 }
466}
467
468TEST(Array_setElement_basicType)
469{
470 jni::Array<int> a(10);
471
472 for (int i = 0; i < 10; i++)
473 a.setElement(i, i);
474
475 for (int i = 0; i < 10; i++)
476 ASSERT(a.getElement(i) == i);
477}
478
479TEST(Array_setElement_string)
480{
481 jni::Array<std::wstring> a(10);
482
483 for (int i = 0; i < 10; i++)
484 a.setElement(i, std::to_wstring(i));
485
486 for (int i = 0; i < 10; i++)
487 ASSERT(a.getElement(i) == std::to_wstring(i));
488}
489
490TEST(Array_setElement_indexException)
491{
492 jni::Array<std::string> s(10);
493
494 try
495 {
496 auto result = s.getElement(1000);
497 ASSERT(0);
498 }
499 catch (jni::Exception&)
500 {
501 ASSERT(1);
502 }
503}
504
505/*
506 Argument Type Tests
507 */
508
509
510TEST(Arg_bool)
511{
512 std::string str1 = jni::Class("java/lang/String").call<std::string>("valueOf", true);
513 std::wstring str2 = jni::Class("java/lang/String").call<std::wstring>("valueOf", true);
514
515 ASSERT(str1 == "true");
516 ASSERT(str2 == L"true");
517}
518
519TEST(Arg_wchar)
520{
521 std::string str1 = jni::Class("java/lang/String").call<std::string>("valueOf", L'X');
522 std::wstring str2 = jni::Class("java/lang/String").call<std::wstring>("valueOf", L'X');
523
524 ASSERT(str1 == "X");
525 ASSERT(str2 == L"X");
526}
527
528TEST(Arg_double)
529{
530 std::string str1 = jni::Class("java/lang/String").call<std::string>("valueOf", 123.0);
531 std::wstring str2 = jni::Class("java/lang/String").call<std::wstring>("valueOf", 123.0);
532
533 ASSERT(str1 == "123.0");
534 ASSERT(str2 == L"123.0");
535}
536
537TEST(Arg_float)
538{
539 std::string str1 = jni::Class("java/lang/String").call<std::string>("valueOf", 123.0f);
540 std::wstring str2 = jni::Class("java/lang/String").call<std::wstring>("valueOf", 123.0f);
541
542 ASSERT(str1 == "123.0");
543 ASSERT(str2 == L"123.0");
544}
545
546TEST(Arg_int)
547{
548 std::string str1 = jni::Class("java/lang/String").call<std::string>("valueOf", 123);
549 std::wstring str2 = jni::Class("java/lang/String").call<std::wstring>("valueOf", 123);
550
551 ASSERT(str1 == "123");
552 ASSERT(str2 == L"123");
553}
554
555TEST(Arg_longLong)
556{
557 std::string str1 = jni::Class("java/lang/String").call<std::string>("valueOf", 123LL);
558 std::wstring str2 = jni::Class("java/lang/String").call<std::wstring>("valueOf", 123LL);
559
560 ASSERT(str1 == "123");
561 ASSERT(str2 == L"123");
562}
563
564TEST(Arg_Object)
565{
566 jni::Object str1 = jni::Class("java/lang/String").newInstance("123");
567 int i = jni::Class("java/lang/Integer").call<int>("parseInt", str1);
568
569 ASSERT(i == 123);
570}
571
572TEST(Arg_ObjectPtr)
573{
574 jni::Object str1 = jni::Class("java/lang/String").newInstance("123");
575 int i = jni::Class("java/lang/Integer").call<int>("parseInt", &str1);
576
577 ASSERT(i == 123);
578}
579
580int main()
581{
582 // Tests that depend on having no JVM
583 RUN_TEST(Object_noDestructorException);
584
585 // jni::Vm Tests
586 RUN_TEST(Vm_detectsJreInstall);
587 RUN_TEST(Vm_notAllowedMultipleVms);
588
589 {
590 jni::Vm vm;
591
592 // jni::Class Tests
593 RUN_TEST(Class_findByName_success);
594 RUN_TEST(Class_findByName_failure);
595 RUN_TEST(Class_getName);
596 RUN_TEST(Class_getParent);
597 RUN_TEST(Class_newInstance);
598 RUN_TEST(Class_newInstance_withArgs);
599 RUN_TEST(Class_getStaticField);
600 RUN_TEST(Class_getMethod);
601 RUN_TEST(Class_getStaticMethod);
602 RUN_TEST(Class_call);
603 RUN_TEST(Class_get_staticField);
604 RUN_TEST(Class_get_staticField_byName);
605 RUN_TEST(Class_call_staticMethod_byName);
606 RUN_TEST(Class_getConstructor);
607
608 // jni::Object Tests
609 RUN_TEST(Object_defaultConstructor_isNull);
610 RUN_TEST(Object_nullary_construct_from_signature);
611 RUN_TEST(Object_copyConstructorIsSameObject);
612 RUN_TEST(Object_moveConstructor);
613 RUN_TEST(Object_copyAssignmentOperator);
614 RUN_TEST(Object_moveAssignmentOperator);
615 RUN_TEST(Object_call);
616 RUN_TEST(Object_call_byName);
617 RUN_TEST(Object_call_withArgs);
618 RUN_TEST(Object_call_byNameWithArgs);
619 RUN_TEST(Object_call_returningArray);
620 RUN_TEST(Object_makeLocalReference);
621
622 // jni::Enum Tests
623 RUN_TEST(Enum_get);
624
625 // jni::Array Tests
626 RUN_TEST(Array_defaultConstructor);
627 RUN_TEST(Array_constructor);
628 RUN_TEST(Array_constructor_eachType);
629 RUN_TEST(Array_constructor_withType);
630 RUN_TEST(Array_copyConstructor);
631 RUN_TEST(Array_moveConstructor);
632 RUN_TEST(Array_getElement_defaultValue);
633 RUN_TEST(Array_getElement_indexException);
634 RUN_TEST(Array_setElement_basicType);
635 RUN_TEST(Array_setElement_string);
636 RUN_TEST(Array_setElement_indexException);
637
638 // Argument Type Tests
639 RUN_TEST(Arg_bool);
640 RUN_TEST(Arg_wchar);
641 RUN_TEST(Arg_double);
642 RUN_TEST(Arg_float);
643 RUN_TEST(Arg_int);
644 RUN_TEST(Arg_longLong);
645 RUN_TEST(Arg_Object);
646 RUN_TEST(Arg_ObjectPtr);
647 }
648
649 return 0;
650}
651