github.com/luchsh/agentlib.go@v0.0.0-20221115155834-ffd0caec4d72/jgo/jvmti_test.go (about)

     1  //
     2  // Copyright 2020 chuanshenglu@gmail.com
     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  package jgo
    18  
    19  import (
    20  	"io/ioutil"
    21  	"os"
    22  	"os/exec"
    23  	"path"
    24  	"strconv"
    25  	"strings"
    26  	"testing"
    27  
    28  	"github.com/ClarkGuan/jni"
    29  	"github.com/stretchr/testify/assert"
    30  )
    31  
    32  const dataDir = "testdata"
    33  
    34  var (
    35  	javaHome string
    36  	javaExec string
    37  	javaMajorVer int
    38  	jvmti jvmtiEnv
    39  )
    40  
    41  
    42  func TestGetjvmtiEnv(t *testing.T) {
    43  	env, e := vm.GetEnv(JVMTI_VERSION_1_1)
    44  	if e != jni.JNI_OK {
    45  		t.Fatalf("Failed to get env")
    46  	}
    47  	assert.NotZero(t, uintptr(env))
    48  }
    49  
    50  func testBasic(t *testing.T) {
    51  	dir := t.TempDir()
    52  
    53  	setup(t)
    54  
    55  	c,_ := ioutil.ReadFile(dataDir+"/Loop.java")
    56  	ioutil.WriteFile(dir+"/Loop.java", c, 0644)
    57  	cmd := exec.Command("javac", dir+"/Loop.java")
    58  	if out,err := cmd.CombinedOutput(); err != nil {
    59  		t.Fatalf("Failed to compile Loop.java\n%s\n",string(out))
    60  	}
    61  
    62  	cwd,_ := os.Getwd()
    63  	defer os.Chdir(cwd)
    64  	os.Chdir(path.Dir(cwd)+"/src")
    65  	cmd = exec.Command("java", "-agentlib:jnigo=hello_options", "-cp", dir, "Loop")
    66  	if out,err := cmd.CombinedOutput(); err != nil {
    67  		t.Fatalf("Failed to run java with agent\n%s\n",string(out))
    68  	} else {
    69  		strout := string(out)
    70  		expectedSubStrs := []string {
    71  			"GO: AgentGoOnload",
    72  			"GO: ClassLoad",
    73  			"GO: Agent command line options: hello_options",
    74  			"GO: OnJvmtiVmInit(): triggered on Go level",
    75  			"agent.go loaded",
    76  			"C: enabled event id=50, name=JVMTI_EVENT_VM_INIT",
    77  			"GO: ClassPrepare event:  ",
    78  		}
    79  		t.Logf("Output:\n%s\n", string(out))
    80  		for _,s := range expectedSubStrs {
    81  			if !strings.Contains(strout, s) {
    82  				t.Fatalf("Cannot find string:\n%s\n", s)
    83  			}
    84  		}
    85  	}
    86  }
    87  
    88  // various setup for the testing
    89  func setup(t *testing.T) {
    90  	// detect if java command presents
    91  	s := os.Getenv("JAVA_HOME")
    92  	if fi, err := os.Lstat("some-filename"); err == nil {
    93  		if m := fi.Mode(); m.IsDir() {
    94  			javaHome = s
    95  			javaExec = javaHome+"/bin/java"
    96  		}
    97  	}
    98  	/*
    99  	javaHome = path.Dir(javaExec)
   100  	cmd := exec.Command("which", "java")
   101  	if out,err := cmd.Output(); err == nil {
   102  		javaExec = string(out)
   103  	} else {
   104  		t.Fatalf("Failed to execute 'which java'")
   105  	}
   106  	*/
   107  
   108  	// check if it is a valid javaexec
   109  	cmd := exec.Command("java", "-version")
   110  	if out,err := cmd.CombinedOutput(); err == nil {
   111  		for _,l := range strings.Split(string(out), "\n") {
   112  			if strings.HasPrefix(l, "java version") {
   113  				s := strings.Split(l, " ")[2]
   114  				s = strings.ReplaceAll(s, "\"", "")
   115  				s = strings.Split(s, ".")[2]
   116  				if v,e := strconv.ParseInt(s, 10, 32); e != nil {
   117  					javaMajorVer = int(v)
   118  				}
   119  			}
   120  		}
   121  	} else {
   122  		t.Fatalf("Cannot run 'java -version'\n%s\n", string(out))
   123  	}
   124  
   125  	// copy testlib to 'src'
   126  	var projRoot string
   127  	cwd,err := os.Getwd()
   128  	if err == nil {
   129  		projRoot = path.Dir(cwd)
   130  		srcDir := projRoot+"/src"
   131  		if c,err := ioutil.ReadFile(dataDir+"/test_lib.go"); err == nil {
   132  			err = ioutil.WriteFile(srcDir+"/test_lib.go", c, 0644)
   133  			if err != nil {
   134  				t.Fatalf("Failed to write to %s/test_lib.go", srcDir)
   135  			}
   136  		} else {
   137  			t.Fatalf("failed to read content of %s/test_lib.go",dataDir)
   138  		}
   139  	} else {
   140  		t.Fatalf("Failed to get cwd")
   141  	}
   142  
   143  	// build the dynamic library
   144  	os.Chdir(projRoot)
   145  	defer os.Chdir(cwd)
   146  	cmd = exec.Command("sh", "-x", "build.sh")
   147  	if out,err := cmd.CombinedOutput(); err != nil {
   148  		t.Fatalf("Failed to compile the library:\n%s\n", string(out))
   149  	} else {
   150  		t.Logf("%s", string(out))
   151  	}
   152  }