Skip to content

Commit

Permalink
Merge pull request #78 from timob/test_coverage
Browse files Browse the repository at this point in the history
Improve test coverage
  • Loading branch information
timob authored Jan 12, 2024
2 parents 9fce18b + d868b47 commit 4d11af2
Show file tree
Hide file tree
Showing 12 changed files with 178 additions and 16 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
java/test/out/*
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ RUN go mod download && go mod verify

COPY . .

CMD go test
CMD ./testing.sh


3 changes: 0 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ This allows for Go to initiate the JVM or Java to start a Go runtime respectivel

Docs: https://pkg.go.dev/tekao.net/jnigi

## Pull Requests
**Please make sure**: `go test` works, add any doc comments for function signature changes.

## v1
As of 2021-12-05 the master branch will be version 2. Packages that used JNIGI before this should update their go.mod to set v1 as the
version. Or update their code to be compatible with version 2.
Expand Down
4 changes: 2 additions & 2 deletions cwrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -646,8 +646,8 @@ const (
JNI_VERSION_1_4 = C.JNI_VERSION_1_4
JNI_VERSION_1_6 = C.JNI_VERSION_1_6
JNI_VERSION_1_8 = C.JNI_VERSION_1_8
JNI_VERSION_9 = C.JNI_VERSION_9
JNI_VERSION_10 = C.JNI_VERSION_10
JNI_VERSION_9 = C.JNI_VERSION_9
JNI_VERSION_10 = C.JNI_VERSION_10

DEFAULT_VERSION = JNI_VERSION_1_6
)
Expand Down
4 changes: 4 additions & 0 deletions java/test/javac.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

cd $(dirname $0)
javac -d out -cp src src/local/*
7 changes: 7 additions & 0 deletions java/test/src/local/JnigiTestBase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package local;

public class JnigiTestBase {
public int meaning() {
return 42;
}
}
7 changes: 7 additions & 0 deletions java/test/src/local/JnigiTestExtend.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package local;

public class JnigiTestExtend extends JnigiTestBase {
public int meaning() {
return 1337;
}
}
5 changes: 5 additions & 0 deletions java/test/src/local/JnigiTesting.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package local;

public class JnigiTesting {
public native java.lang.String Greet(java.lang.String x);
}
121 changes: 112 additions & 9 deletions jnigi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@
package jnigi

import (
"github.com/stretchr/testify/assert"
"os"
"path/filepath"
"runtime"
"strings"
"syscall"
"testing"

"github.com/stretchr/testify/assert"
)

var env *Env
Expand All @@ -28,6 +32,8 @@ func TestAll(t *testing.T) {
PTestPushPopLocalFrame(t)
PTestHandleException(t)
PTestCast(t)
PTestNonVirtual(t)
PTestRegisterNative(t)
PTestDestroy(t)
}

Expand All @@ -39,7 +45,8 @@ func PTestInit(t *testing.T) {
t.Fatal(err)
}
runtime.LockOSThread()
jvm2, e2, err := CreateJVM(NewJVMInitArgs(false, true, DEFAULT_VERSION, []string{"-Xcheck:jni"}))
cwd, _ := os.Getwd()
jvm2, e2, err := CreateJVM(NewJVMInitArgs(false, true, DEFAULT_VERSION, []string{"-Xcheck:jni", "-Djava.class.path=" + filepath.Join(cwd, "java/test/out")}))
if err != nil {
t.Fatal(err)
}
Expand All @@ -59,6 +66,7 @@ func PTestBasic(t *testing.T) {
if err := obj.CallMethod(env, "hashCode", &v); err != nil {
t.Fatal(err)
}
env.DeleteLocalRef(obj)

// test env.GetUTF8String() should be independent of PrecalculateSignature
sigStr := "dummy"
Expand All @@ -75,6 +83,7 @@ func PTestBasic(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer env.DeleteLocalRef(str)
var goBytes []byte
if err := str.CallMethod(env, "getBytes", &goBytes, env.GetUTF8String()); err != nil {
t.Fatal(err)
Expand All @@ -88,6 +97,8 @@ func PTestBasic(t *testing.T) {
if err := str.CallMethod(env, "substring", str2, 6); err != nil {
t.Fatal(err)
}
defer env.DeleteLocalRef(str2)

var dummy []byte
if err := str2.CallMethod(env, "getBytes", &dummy); err != nil {
t.Fatal(err)
Expand All @@ -109,17 +120,26 @@ func PTestBasic(t *testing.T) {
}

// get static field
err = env.SetStaticField("java/util/Calendar", "APRIL", 5)
if err != nil {
t.Fatal(err)
}
var calPos int
err = env.GetStaticField("java/util/Calendar", "APRIL", &calPos)
if err != nil {
t.Fatal(err)
}
if !assert.Equal(t, 5, calPos) {
t.Fail()
}

// set/get object field
pt, err := env.NewObject("java/awt/Point")
if err != nil {
t.Fatal(err)
}
defer env.DeleteLocalRef(pt)

err = pt.SetField(env, "x", 5)
if err != nil {
t.Fatal(err)
Expand All @@ -142,6 +162,7 @@ func PTestBasic(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer env.DeleteLocalRef(str)

if err := str.CallMethod(env, "getBytes", &goBytes, env.GetUTF8String()); err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -179,6 +200,8 @@ func PTestAttach(t *testing.T) {
}()

<-x
env.DeleteGlobalRef(gObj)
env.DeleteLocalRef(obj)
}

func PTestObjectArrays(t *testing.T) {
Expand All @@ -187,11 +210,12 @@ func PTestObjectArrays(t *testing.T) {
if err != nil {
t.Fatal(err)
}

defer env.DeleteLocalRef(str)
regex, err := env.NewObject("java/lang/String", []byte("X"))
if err != nil {
t.Fatal(err)
}
defer env.DeleteLocalRef(regex)

v := NewObjectArrayRef("java/lang/String")
if err := str.CallMethod(env, "split", v, regex); err != nil {
Expand All @@ -217,10 +241,12 @@ func PTestObjectArrays(t *testing.T) {
if err := array.CallMethod(env, "getClass", class); err != nil {
t.Fatal(err)
}
defer env.DeleteLocalRef(class)
jClassName := NewObjectRef("java/lang/String")
if err := class.CallMethod(env, "getName", jClassName); err != nil {
t.Fatal(err)
}
defer env.DeleteLocalRef(jClassName)
var className []byte
if err := jClassName.CallMethod(env, "getBytes", &className); err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -260,6 +286,7 @@ func PTestConvert(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer env.DeleteLocalRef(str)

var firstWord GoString
if err := str.CallMethod(env, "substring", &firstWord, 0, 4); err != nil {
Expand All @@ -275,11 +302,14 @@ func PTestInstanceOf(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer env.DeleteLocalRef(alist)

str, err := env.NewObject("java/lang/String")
if err != nil {
t.Fatal(err)
}
defer env.DeleteLocalRef(str)

var dummy bool
if err := alist.CallMethod(env, "add", &dummy, str.Cast("java/lang/Object")); err != nil {
t.Fatal(err)
Expand All @@ -289,6 +319,7 @@ func PTestInstanceOf(t *testing.T) {
if err := alist.CallMethod(env, "get", obj, 0); err != nil {
t.Fatal(err)
}
defer env.DeleteLocalRef(obj)

if isInstance, err := obj.IsInstanceOf(env, "java/lang/String"); err != nil {
t.Fatal(err)
Expand All @@ -309,24 +340,32 @@ func PTestByteArray(t *testing.T) {
if !assert.Equal(t, "hello", toGoStr(t, str)) {
t.Fail()
}
env.DeleteLocalRef(str)

testStr := "hello world"
str, err = env.NewObject("java/lang/String", []byte(testStr))
if err != nil {
t.Fatal(err)
}
defer env.DeleteLocalRef(str)

arr := NewArrayRef(Byte | Array)
if err := str.CallMethod(env, "getBytes", arr, env.GetUTF8String()); err != nil {
t.Fatal(err)
}

ba2 := env.NewByteArrayFromObject(arr.ObjectRef)
bytes = ba2.GetCritical(env)

bytes = ba2.CopyBytes(env)
if !assert.Equal(t, "hello world", string(bytes)) {
t.Fail()
}
ba2.ReleaseCritical(env, bytes)

ba3 := env.NewByteArrayFromSlice([]byte("hello world!"))
bytes = ba3.CopyBytes(env)
if !assert.Equal(t, "hello world!", string(bytes)) {
t.Fail()
}
}

func PTestGetJVM(t *testing.T) {
Expand Down Expand Up @@ -400,23 +439,49 @@ func PTestPushPopLocalFrame(t *testing.T) {
}
}

func runWithStderrRedir(f func() error) error {
// redirect standard err
stdErrFd := int(os.Stderr.Fd())
newFd, err := syscall.Dup(stdErrFd)
if err != nil {
return err
}
devNull, err := os.OpenFile(os.DevNull, os.O_WRONLY, 000)
if err != nil {
return err
}
syscall.Dup2(int(devNull.Fd()), stdErrFd)
err = f()
syscall.Dup2(newFd, stdErrFd)

return err
}

func newObjWithStderrRedir(class string) error {
err := runWithStderrRedir(func() error {
_, err := env.NewObject(class)
return err
})
return err
}

func PTestHandleException(t *testing.T) {
jexceptErrMsg := "Java exception occurred. check stderr/logcat"
if _, err := env.NewObject("java/foo/bar"); err == nil {
if err := newObjWithStderrRedir("java/foo/bar"); err == nil {
t.Fatal("did not return error")
} else if !assert.Equal(t, jexceptErrMsg, err.Error()) {
t.Fatal("did not return standard error")
}

env.ExceptionHandler = ThrowableToStringExceptionHandler
if _, err := env.NewObject("java/foo/bar"); err == nil {
if err := newObjWithStderrRedir("java/foo/bar"); err == nil {
t.Fatal("did not return error")
} else if !assert.Equal(t, "java.lang.NoClassDefFoundError: java/foo/bar", err.Error()) {
t.Fatal("did not return standard error")
}

env.ExceptionHandler = ThrowableErrorExceptionHandler
if _, err := env.NewObject("java/foo/bar"); err == nil {
if err := newObjWithStderrRedir("java/foo/bar"); err == nil {
t.Fatal("did not return error")
} else {
throwableError, ok := err.(ThrowableError)
Expand Down Expand Up @@ -471,11 +536,12 @@ func PTestHandleException(t *testing.T) {

env.ExceptionHandler = nil

if _, err := env.NewObject("java/foo/bar"); err == nil {
if err := newObjWithStderrRedir("java/foo/bar"); err == nil {
t.Fatal("did not return error")
} else if !assert.Equal(t, jexceptErrMsg, err.Error()) {
t.Error("did not return standard error")
}

}

func PTestCast(t *testing.T) {
Expand All @@ -491,6 +557,43 @@ func PTestCast(t *testing.T) {
}
}

func PTestNonVirtual(t *testing.T) {
obj, err := env.NewObject("local/JnigiTestExtend")
if err != nil {
t.Fatal(err)
}
var val int
if err := obj.CallNonvirtualMethod(env, "local/JnigiTestBase", "meaning", &val); err != nil {
t.Fatal(err)
}

if !assert.Equal(t, 42, val) {
t.Fail()
}
}

func PTestRegisterNative(t *testing.T) {
if err := env.RegisterNative("local/JnigiTesting", "Greet", ObjectType("java/lang/String"), []interface{}{ObjectType("java/lang/String")}, c_go_callback_Greet); err != nil {
t.Fatal(err)
}
objRef, err := env.NewObject("local/JnigiTesting")
if err != nil {
t.Fatal(err)
}
nameRef, err := env.NewObject("java/lang/String", []byte("World"))
if err != nil {
t.Fatal(err)
}
strRef := NewObjectRef("java/lang/String")
if err := objRef.CallMethod(env, "Greet", strRef, nameRef); err != nil {
t.Fatal(err)
}
goStr := toGoStr(t, strRef)
if !assert.Equal(t, "Hello World!", goStr) {
t.Fail()
}
}

func toGoStr(t *testing.T, o *ObjectRef) string {
var goBytes []byte
if err := o.CallMethod(env, "getBytes", &goBytes); err != nil {
Expand Down
Loading

0 comments on commit 4d11af2

Please sign in to comment.