// +build !android //go:generate javac test/AClass.java test/AClass2.java package jni import ( "sync" "testing" "unsafe" ) var ( vm JVM vmOnce sync.Once ) func TestCreateJVM(t *testing.T) { // Do not try to create more than one JVM vmOnce.Do(func() { res := CreateJavaVM() if res.jvm == nil { t.Errorf("CreateJavaVM() returned nil") } else { vm = res } }) } func TestDo(t *testing.T) { // create an invalid JVM vm2 := JVMFor(uintptr(unsafe.Pointer(vm.jvm))) err := Do(vm2, func(env Env) error { return nil }) if err != nil { t.Errorf("Do() returned an error") } } func TestFindClass(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") if cls == 0 { t.Errorf("Class is nil") } return nil }) if err != nil { t.Errorf("Error: %s", err) } defer func() { if r := recover(); r == nil { t.Errorf("No exception for class not found") } else { t.Logf("Panic: %s", r) } }() err = Do(vm, func(env Env) error { cls := FindClass(env, "test/NoSuchClass") if cls == 0 { t.Errorf("Class is nil") } return nil }) } func TestEnvFor(t *testing.T) { err := Do(vm, func(env Env) error { env2 := EnvFor(uintptr(unsafe.Pointer(env.env))) cls := FindClass(env2, "test/AClass") if cls == 0 { t.Errorf("Class is nil") } return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestGetMethodID(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") if mid == nil { t.Errorf("MethodID is nil") } return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestNewObject(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, err := NewObject(env, cls, mid) if err != nil { t.Errorf("NewObject raised exception") } if inst == 0 { t.Errorf("NewObject returned nil") } inst = NewGlobalRef(env, inst) if inst == 0 { t.Errorf("NewGlobalRef returned nil") } DeleteGlobalRef(env, inst) return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestIsSameObject(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, err := NewObject(env, cls, mid) if !IsSameObject(env, inst, inst) { t.Errorf("Object is not the same as itself") } inst2, err := NewObject(env, cls, mid) if err != nil { t.Errorf("Object is nil") } if IsSameObject(env, inst, inst2) { t.Errorf("Different objects are the same") } inst2 = NewLocalRef(env, inst) if !IsSameObject(env, inst, inst2) { t.Errorf("New local ref is not the same as original object") } DeleteLocalRef(env, inst) return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestStaticMethod(t *testing.T) { defer func() { if r := recover(); r == nil { t.Errorf("GetStaticMethodID() did not panic") } else { t.Logf("Panic: %s", r) } }() Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") GetStaticMethodID(env, cls, "noSuchMethod", "()V") return nil }) } func TestStaticIntMethod(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") mid = GetStaticMethodID(env, cls, "GetStaticInt", "()I") if mid == nil { t.Errorf("MethodID is nil") } res, err := CallStaticIntMethod(env, cls, mid) if err != nil { t.Errorf("Method invocation failed") } if res != 100 { t.Errorf("Method returned %d, not expected value of %d.", res, 100) } return err }) if err != nil { t.Errorf("Error: %s", err) } } func TestStaticObjectMethod(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") mid = GetStaticMethodID(env, cls, "GetStaticObject", "()Ljava/lang/Object;") if mid == nil { t.Errorf("MethodID is nil") } _, err := CallStaticObjectMethod(env, cls, mid) if err != nil { t.Errorf("Method invocation failed") } return err }) if err != nil { t.Errorf("Error: %s", err) } } func TestMethod(t *testing.T) { defer func() { if r := recover(); r == nil { t.Errorf("GetMethodID() did not panic") } else { t.Logf("Panic: %s", r) } }() Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") GetMethodID(env, cls, "noSuchMethod", "()V") return nil }) } func TestIntMethod(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, err := NewObject(env, cls, mid) mid = GetMethodID(env, cls, "GetInt", "()I") if mid == nil { t.Errorf("MethodID is nil") } res, err := CallIntMethod(env, inst, mid) if err != nil { t.Errorf("Method invocation failed") } if res != 101 { t.Errorf("Method returned %d, not expected value of %d.", res, 0) } return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestBooleanMethod(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, err := NewObject(env, cls, mid) mid = GetMethodID(env, cls, "GetBoolean", "()Z") if mid == nil { t.Errorf("MethodID is nil") } res, err := CallBooleanMethod(env, inst, mid) if err != nil { t.Errorf("Method invocation failed") } if !res { t.Errorf("Method returned %v, not expected value of %v.", res, true) } return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestByteMethod(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, err := NewObject(env, cls, mid) mid = GetMethodID(env, cls, "GetByte", "()B") if mid == nil { t.Errorf("MethodID is nil") } res, err := CallByteMethod(env, inst, mid) if err != nil { t.Errorf("Method invocation failed") } if res != 127 { t.Errorf("Method returned %d, not expected value of %d.", res, 127) } return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestCharMethod(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, err := NewObject(env, cls, mid) mid = GetMethodID(env, cls, "GetChar", "()C") if mid == nil { t.Errorf("MethodID is nil") } res, err := CallCharMethod(env, inst, mid) if err != nil { t.Errorf("Method invocation failed") } if res != 65432 { t.Errorf("Method returned %d, not expected value of %d.", res, 65432) } return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestShortMethod(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, err := NewObject(env, cls, mid) mid = GetMethodID(env, cls, "GetShort", "()S") if mid == nil { t.Errorf("MethodID is nil") } res, err := CallShortMethod(env, inst, mid) if err != nil { t.Errorf("Method invocation failed") } if res != 512 { t.Errorf("Method returned %d, not expected value of %d.", res, 512) } return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestLongMethod(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, err := NewObject(env, cls, mid) mid = GetMethodID(env, cls, "GetLong", "()J") if mid == nil { t.Errorf("MethodID is nil") } res, err := CallLongMethod(env, inst, mid) if err != nil { t.Errorf("Method invocation failed") } if res != 1<<33 { t.Errorf("Method returned %d, not expected value of %d.", res, 1<<33) } return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestFloatMethod(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, err := NewObject(env, cls, mid) mid = GetMethodID(env, cls, "GetFloat", "()F") if mid == nil { t.Errorf("MethodID is nil") } res, err := CallFloatMethod(env, inst, mid) if err != nil { t.Errorf("Method invocation failed") } if res != 4.321 { t.Errorf("Method returned %f, not expected value of %f.", res, 4.321) } return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestDoubleMethod(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, err := NewObject(env, cls, mid) mid = GetMethodID(env, cls, "GetDouble", "()D") if mid == nil { t.Errorf("MethodID is nil") } res, err := CallDoubleMethod(env, inst, mid) if err != nil { t.Errorf("Method invocation failed") } if res != 5.4321 { t.Errorf("Method returned %f, not expected value of %f.", res, 5.4321) } return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestVoidMethod(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, err := NewObject(env, cls, mid) mid = GetMethodID(env, cls, "IncInt", "()V") if mid == nil { t.Errorf("MethodID is nil") } err = CallVoidMethod(env, inst, mid) if err != nil { t.Errorf("Method invocation failed") } return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestVoidMethod2(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, err := NewObject(env, cls, mid) mid = GetMethodID(env, cls, "SetInt", "(I)V") if mid == nil { t.Errorf("MethodID is nil") } err = CallVoidMethod(env, inst, mid, 5) if err != nil { t.Errorf("Method invocation failed") } mid = GetMethodID(env, cls, "GetInt", "()I") res, err := CallIntMethod(env, inst, mid) if err != nil { t.Errorf("Method invocation falied") } if res != 5 { t.Errorf("Method returned %d, not expected value of %d.", res, 5) } return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestVoidMethod3(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, err := NewObject(env, cls, mid) mid = GetMethodID(env, cls, "AddInts", "(II)V") if mid == nil { t.Errorf("MethodID is nil") } err = CallVoidMethod(env, inst, mid, 9, 11) if err != nil { t.Errorf("Method invocation failed") } mid = GetMethodID(env, cls, "GetInt", "()I") res, err := CallIntMethod(env, inst, mid) if err != nil { t.Errorf("Method invocation falied") } if res != 20 { t.Errorf("Method returned %d, not expected value of %d.", res, 20) } return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestStaticVoidMethod(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetStaticMethodID(env, cls, "SetStaticInt", "(I)V") if mid == nil { t.Errorf("MethodID is nil") } err := CallStaticVoidMethod(env, cls, mid, 200) if err != nil { t.Errorf("Method invocation failed: %s", err) } mid = GetStaticMethodID(env, cls, "GetStaticInt", "()I") res, err := CallStaticIntMethod(env, cls, mid) if err != nil { t.Errorf("Method invocation falied: %s", err) } if res != 200 { t.Errorf("Method returned %d, not expected value of %d.", res, 200) } mid = GetStaticMethodID(env, cls, "SetStaticInt", "(I)V") err = CallStaticVoidMethod(env, cls, mid, 100) if err != nil { t.Errorf("Method invocation failed: %s", err) } return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestGetObjectClass(t *testing.T) { defer func() { if r := recover(); r == nil { t.Errorf("GetObjectClass() did not panic") } else { t.Logf("Panic: %s", r) } }() err := Do(vm, func(env Env) error { GetObjectClass(env, Object(unsafe.Pointer(uintptr(0)))) return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestGetObjectClass2(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, _ := NewObject(env, cls, mid) cls2 := GetObjectClass(env, inst) if cls2 == 0 { t.Errorf("GetObjectClass returned nil") } if !IsInstanceOf(env, inst, cls2) { t.Errorf("IsInstanceOf failed") } return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestIsInstanceOf(t *testing.T) { defer func() { if r := recover(); r == nil { t.Errorf("IsInstanceOf() did not panic") } else { t.Logf("Panic: %s", r) } }() err := Do(vm, func(env Env) error { IsInstanceOf(env, Object(0), Class(0)) return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestIsInstanceOf2(t *testing.T) { defer func() { if r := recover(); r == nil { t.Errorf("IsInstanceOf() did not panic") } else { t.Logf("Panic: %s", r) } }() err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, _ := NewObject(env, cls, mid) IsInstanceOf(env, inst, Class(0)) return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestIsInstanceOf3(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, _ := NewObject(env, cls, mid) cls = FindClass(env, "java/lang/String") if IsInstanceOf(env, inst, cls) { t.Errorf("IsInstanceOf() returned wrong value") } return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestField(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, _ := NewObject(env, cls, mid) fid := GetFieldID(env, cls, "in", "I") if fid == nil { t.Errorf("FieldID is nil") } r1 := GetIntField(env, inst, fid) if r1 != 101 { t.Errorf("Method returned %d, not expected value of %d.", r1, 0) } fid = GetFieldID(env, cls, "bl", "Z") if fid == nil { t.Errorf("FieldID is nil") } r2 := GetBooleanField(env, inst, fid) if r2 != false { t.Errorf("Boolean field value is incorrect") } fid = GetFieldID(env, cls, "bt", "B") if fid == nil { t.Errorf("FieldID is nil") } r3 := GetByteField(env, inst, fid) if r3 != 'c' { t.Errorf("Byte field value is incorrect") } fid = GetFieldID(env, cls, "ch", "C") if fid == nil { t.Errorf("FieldID is nil") } r4 := GetCharField(env, inst, fid) if r4 != 'd' { t.Errorf("Char field value is incorrect") } fid = GetFieldID(env, cls, "obj", "Ljava/lang/Object;") if fid == nil { t.Errorf("FieldID is nil") } r5 := GetObjectField(env, inst, fid) if r5 == 0 { t.Errorf("Object field value is incorrect") } fid = GetFieldID(env, cls, "sh", "S") if fid == nil { t.Errorf("FieldID is nil") } r6 := GetShortField(env, inst, fid) if r6 != 11 { t.Errorf("Short field value is incorrect") } fid = GetFieldID(env, cls, "lo", "J") if fid == nil { t.Errorf("FieldID is nil") } r7 := GetLongField(env, inst, fid) if r7 != 1001 { t.Errorf("Long field value is incorrect") } fid = GetFieldID(env, cls, "fl", "F") if fid == nil { t.Errorf("FieldID is nil") } r8 := GetFloatField(env, inst, fid) if r8 != 2.2 { t.Errorf("Float field value is incorrect") } fid = GetFieldID(env, cls, "db", "D") if fid == nil { t.Errorf("FieldID is nil") } r9 := GetDoubleField(env, inst, fid) if r9 != 1001.1001 { t.Errorf("Double field value is incorrect") } return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestField2(t *testing.T) { defer func() { if r := recover(); r == nil { t.Errorf("GetFieldID() did not panic") } else { t.Logf("Panic: %s", r) } }() Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") GetFieldID(env, cls, "noSuchField", "I") return nil }) } func TestStaticField(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") fid := GetStaticFieldID(env, cls, "staticint", "I") if fid == nil { t.Errorf("FieldID is nil") } r1 := GetStaticIntField(env, cls, fid) if r1 != 100 { t.Errorf("Method returned %d, not expected value of %d.", r1, 100) } fid = GetStaticFieldID(env, cls, "staticbl", "Z") if fid == nil { t.Errorf("FieldID is nil") } r2 := GetStaticBooleanField(env, cls, fid) if r2 != true { t.Errorf("Boolean field value is incorrect") } fid = GetStaticFieldID(env, cls, "staticbt", "B") if fid == nil { t.Errorf("FieldID is nil") } r3 := GetStaticByteField(env, cls, fid) if r3 != 'a' { t.Errorf("Byte field value is incorrect") } fid = GetStaticFieldID(env, cls, "staticch", "C") if fid == nil { t.Errorf("FieldID is nil") } r4 := GetStaticCharField(env, cls, fid) if r4 != 'b' { t.Errorf("Char field value is incorrect") } fid = GetStaticFieldID(env, cls, "staticobj", "Ljava/lang/Object;") if fid == nil { t.Errorf("FieldID is nil") } r5 := GetStaticObjectField(env, cls, fid) if r5 == 0 { t.Errorf("Object field value is incorrect") } fid = GetStaticFieldID(env, cls, "staticsh", "S") if fid == nil { t.Errorf("FieldID is nil") } r6 := GetStaticShortField(env, cls, fid) if r6 != 10 { t.Errorf("Short field value is incorrect") } fid = GetStaticFieldID(env, cls, "staticlo", "J") if fid == nil { t.Errorf("FieldID is nil") } r7 := GetStaticLongField(env, cls, fid) if r7 != 1000 { t.Errorf("Long field value is incorrect") } fid = GetStaticFieldID(env, cls, "staticfl", "F") if fid == nil { t.Errorf("FieldID is nil") } r8 := GetStaticFloatField(env, cls, fid) if r8 != 1.1 { t.Errorf("Float field value is incorrect") } fid = GetStaticFieldID(env, cls, "staticdb", "D") if fid == nil { t.Errorf("FieldID is nil") } r9 := GetStaticDoubleField(env, cls, fid) if r9 != 1000.0001 { t.Errorf("Double field value is incorrect") } return nil }) if err != nil { t.Errorf("Error: %s", err) } } func TestStaticField2(t *testing.T) { defer func() { if r := recover(); r == nil { t.Errorf("GetStaticField() did not panic") } else { t.Logf("Panic: %s", r) } }() Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") fid := GetStaticFieldID(env, cls, "FieldNotFound", "I") GetStaticIntField(env, cls, fid) return nil }) } func TestByteArray(t *testing.T) { arr := []byte{'a', 'b', 'c'} Do(vm, func(env Env) error { jarr := NewByteArray(env, arr) arr2 := GetByteArrayElements(env, jarr) if arr2[0] != 'a' || arr2[1] != 'b' || arr2[2] != 'c' || len(arr2) != 3 { t.Errorf("GetByteArrayElements() failed") } return nil }) } func TestObjectArray(t *testing.T) { Do(vm, func(env Env) error { cls := FindClass(env, "java/lang/Object") if cls == 0 { t.Errorf("Class is nil") } strings := []string{ "item1", "item2", } arr := NewObjectArray(env, Size(len(strings)), cls, 0) for i, s := range strings { jstring := JavaString(env, s) err := SetObjectArrayElement(env, arr, Size(i), Object(jstring)) if err != nil { t.Errorf("SetObjectArrayElement at index %d raised exception", i) } } for i, s := range strings { r, err := GetObjectArrayElement(env, arr, Size(i)) if err != nil { t.Errorf("GetObjectArrayElement at index %d raised exception", i) } retrieved := GoString(env, String(r)) if s != retrieved { t.Errorf("Expected item %d to be '%s' but instead was '%s'", i, s, retrieved) } } return nil }) } func TestClassLoaderFor(t *testing.T) { defer func() { if r := recover(); r == nil { t.Errorf("ClassLoaderFor() did not panic") } else { t.Logf("Panic: %s", r) } }() Do(vm, func(env Env) error { cls := FindClass(env, "java/lang/Object") if cls == 0 { t.Errorf("Class is nil") } mid := GetMethodID(env, cls, "", "()V") if mid == nil { t.Errorf("Method ID is nil") } inst, err := NewObject(env, cls, mid) if err != nil { t.Errorf("NewObject raised exception") } if inst == 0 { t.Errorf("NewObject returned nil") } ClassLoaderFor(env, inst) return nil }) } func TestClassLoaderFor2(t *testing.T) { Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, _ := NewObject(env, cls, mid) cl := ClassLoaderFor(env, inst) if cl == 0 { t.Errorf("ClassLoaderFor() returned nil") } return nil }) } func TestClassLoaderFor3(t *testing.T) { defer func() { if r := recover(); r == nil { t.Errorf("ClassLoaderFor() did not panic") } else { t.Logf("Panic: %s", r) } }() Do(vm, func(env Env) error { cls := FindClass(env, "java/lang/Object") mid := GetMethodID(env, cls, "", "()V") inst, _ := NewObject(env, cls, mid) cl := ClassLoaderFor(env, inst) if cl == 0 { t.Errorf("ClassLoaderFor() returned nil") } return nil }) } func TestClassLoaderFor4(t *testing.T) { defer func() { if r := recover(); r == nil { t.Errorf("ClassLoaderFor() did not panic") } else { t.Logf("Panic: %s", r) } }() Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass2") mid := GetMethodID(env, cls, "", "()V") inst, _ := NewObject(env, cls, mid) cl := ClassLoaderFor(env, inst) if cl == 0 { t.Errorf("ClassLoaderFor() returned nil") } return nil }) } func TestLoadClass(t *testing.T) { Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, _ := NewObject(env, cls, mid) cl := ClassLoaderFor(env, inst) if cl == 0 { t.Errorf("ClassLoaderFor() returned nil") } cls, err := LoadClass(env, cl, "java.lang.String") if err != nil { t.Errorf("LoadClass() returned error: %s", err) } if cls == 0 { t.Errorf("LoadClass() failed") } return nil }) } func TestLoadClass2(t *testing.T) { Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, _ := NewObject(env, cls, mid) _, err := LoadClass(env, inst, "java.lang.String") if err == nil { t.Errorf("LoadClass() did not return an error") } else { t.Logf("Error: %s", err) } return nil }) } func TestJavaString(t *testing.T) { Do(vm, func(env Env) error { jstr := JavaString(env, "") if jstr != 0 { t.Errorf("String is not nil") } gstr := GoString(env, jstr) if gstr != "" { t.Errorf("String is not empty") } jstr = JavaString(env, "test string") gstr = GoString(env, jstr) if gstr != "test string" { t.Errorf("Strings do not match") } return nil }) }