github.com/maier/nomad@v0.4.1-0.20161110003312-a9e3d0b8549d/client/driver/java_test.go (about)

     1  package driver
     2  
     3  import (
     4  	"os"
     5  	"os/exec"
     6  	"path/filepath"
     7  	"runtime"
     8  	"strings"
     9  	"syscall"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/hashicorp/nomad/client/config"
    14  	"github.com/hashicorp/nomad/nomad/structs"
    15  	"github.com/hashicorp/nomad/testutil"
    16  
    17  	ctestutils "github.com/hashicorp/nomad/client/testutil"
    18  )
    19  
    20  var (
    21  	osJavaDriverSupport = map[string]bool{
    22  		"linux": true,
    23  	}
    24  )
    25  
    26  // javaLocated checks whether java is installed so we can run java stuff.
    27  func javaLocated() bool {
    28  	_, err := exec.Command("java", "-version").CombinedOutput()
    29  	return err == nil
    30  }
    31  
    32  // The fingerprinter test should always pass, even if Java is not installed.
    33  func TestJavaDriver_Fingerprint(t *testing.T) {
    34  	ctestutils.JavaCompatible(t)
    35  	task := &structs.Task{
    36  		Name:      "foo",
    37  		Resources: structs.DefaultResources(),
    38  	}
    39  	driverCtx, execCtx := testDriverContexts(task)
    40  	defer execCtx.AllocDir.Destroy()
    41  	d := NewJavaDriver(driverCtx)
    42  	node := &structs.Node{
    43  		Attributes: map[string]string{
    44  			"unique.cgroup.mountpoint": "/sys/fs/cgroups",
    45  		},
    46  	}
    47  	apply, err := d.Fingerprint(&config.Config{}, node)
    48  	if err != nil {
    49  		t.Fatalf("err: %v", err)
    50  	}
    51  	if apply != javaLocated() {
    52  		t.Fatalf("Fingerprinter should detect Java when it is installed")
    53  	}
    54  	if node.Attributes["driver.java"] != "1" {
    55  		if v, ok := osJavaDriverSupport[runtime.GOOS]; v && ok {
    56  			t.Fatalf("missing java driver")
    57  		} else {
    58  			t.Skipf("missing java driver, no OS support")
    59  		}
    60  	}
    61  	for _, key := range []string{"driver.java.version", "driver.java.runtime", "driver.java.vm"} {
    62  		if node.Attributes[key] == "" {
    63  			t.Fatalf("missing driver key (%s)", key)
    64  		}
    65  	}
    66  }
    67  
    68  func TestJavaDriver_StartOpen_Wait(t *testing.T) {
    69  	if !javaLocated() {
    70  		t.Skip("Java not found; skipping")
    71  	}
    72  
    73  	ctestutils.JavaCompatible(t)
    74  	task := &structs.Task{
    75  		Name: "demo-app",
    76  		Config: map[string]interface{}{
    77  			"jar_path":    "demoapp.jar",
    78  			"jvm_options": []string{"-Xmx64m", "-Xms32m"},
    79  		},
    80  		LogConfig: &structs.LogConfig{
    81  			MaxFiles:      10,
    82  			MaxFileSizeMB: 10,
    83  		},
    84  		Resources: basicResources,
    85  	}
    86  
    87  	driverCtx, execCtx := testDriverContexts(task)
    88  	defer execCtx.AllocDir.Destroy()
    89  	d := NewJavaDriver(driverCtx)
    90  
    91  	// Copy the test jar into the task's directory
    92  	dst, _ := execCtx.AllocDir.TaskDirs[task.Name]
    93  	copyFile("./test-resources/java/demoapp.jar", filepath.Join(dst, "demoapp.jar"), t)
    94  
    95  	handle, err := d.Start(execCtx, task)
    96  	if err != nil {
    97  		t.Fatalf("err: %v", err)
    98  	}
    99  	if handle == nil {
   100  		t.Fatalf("missing handle")
   101  	}
   102  
   103  	// Attempt to open
   104  	handle2, err := d.Open(execCtx, handle.ID())
   105  	if err != nil {
   106  		t.Fatalf("err: %v", err)
   107  	}
   108  	if handle2 == nil {
   109  		t.Fatalf("missing handle")
   110  	}
   111  
   112  	time.Sleep(2 * time.Second)
   113  
   114  	// There is a race condition between the handle waiting and killing. One
   115  	// will return an error.
   116  	handle.Kill()
   117  	handle2.Kill()
   118  }
   119  
   120  func TestJavaDriver_Start_Wait(t *testing.T) {
   121  	if !javaLocated() {
   122  		t.Skip("Java not found; skipping")
   123  	}
   124  
   125  	ctestutils.JavaCompatible(t)
   126  	task := &structs.Task{
   127  		Name: "demo-app",
   128  		Config: map[string]interface{}{
   129  			"jar_path": "demoapp.jar",
   130  		},
   131  		LogConfig: &structs.LogConfig{
   132  			MaxFiles:      10,
   133  			MaxFileSizeMB: 10,
   134  		},
   135  		Resources: basicResources,
   136  	}
   137  
   138  	driverCtx, execCtx := testDriverContexts(task)
   139  	d := NewJavaDriver(driverCtx)
   140  
   141  	// Copy the test jar into the task's directory
   142  	dst, _ := execCtx.AllocDir.TaskDirs[task.Name]
   143  	copyFile("./test-resources/java/demoapp.jar", filepath.Join(dst, "demoapp.jar"), t)
   144  
   145  	handle, err := d.Start(execCtx, task)
   146  	if err != nil {
   147  		t.Fatalf("err: %v", err)
   148  	}
   149  	if handle == nil {
   150  		t.Fatalf("missing handle")
   151  	}
   152  
   153  	// Task should terminate quickly
   154  	select {
   155  	case res := <-handle.WaitCh():
   156  		if !res.Successful() {
   157  			t.Fatalf("err: %v", res)
   158  		}
   159  	case <-time.After(time.Duration(testutil.TestMultiplier()*5) * time.Second):
   160  		// expect the timeout b/c it's a long lived process
   161  		break
   162  	}
   163  
   164  	// Get the stdout of the process and assrt that it's not empty
   165  	stdout := filepath.Join(execCtx.AllocDir.LogDir(), "demo-app.stdout.0")
   166  	fInfo, err := os.Stat(stdout)
   167  	if err != nil {
   168  		t.Fatalf("failed to get stdout of process: %v", err)
   169  	}
   170  	if fInfo.Size() == 0 {
   171  		t.Fatalf("stdout of process is empty")
   172  	}
   173  
   174  	// need to kill long lived process
   175  	err = handle.Kill()
   176  	if err != nil {
   177  		t.Fatalf("Error: %s", err)
   178  	}
   179  }
   180  
   181  func TestJavaDriver_Start_Kill_Wait(t *testing.T) {
   182  	if !javaLocated() {
   183  		t.Skip("Java not found; skipping")
   184  	}
   185  
   186  	ctestutils.JavaCompatible(t)
   187  	task := &structs.Task{
   188  		Name: "demo-app",
   189  		Config: map[string]interface{}{
   190  			"jar_path": "demoapp.jar",
   191  		},
   192  		LogConfig: &structs.LogConfig{
   193  			MaxFiles:      10,
   194  			MaxFileSizeMB: 10,
   195  		},
   196  		Resources: basicResources,
   197  	}
   198  
   199  	driverCtx, execCtx := testDriverContexts(task)
   200  	defer execCtx.AllocDir.Destroy()
   201  	d := NewJavaDriver(driverCtx)
   202  
   203  	// Copy the test jar into the task's directory
   204  	dst, _ := execCtx.AllocDir.TaskDirs[task.Name]
   205  	copyFile("./test-resources/java/demoapp.jar", filepath.Join(dst, "demoapp.jar"), t)
   206  
   207  	handle, err := d.Start(execCtx, task)
   208  	if err != nil {
   209  		t.Fatalf("err: %v", err)
   210  	}
   211  	if handle == nil {
   212  		t.Fatalf("missing handle")
   213  	}
   214  
   215  	go func() {
   216  		time.Sleep(100 * time.Millisecond)
   217  		err := handle.Kill()
   218  		if err != nil {
   219  			t.Fatalf("err: %v", err)
   220  		}
   221  	}()
   222  
   223  	// Task should terminate quickly
   224  	select {
   225  	case res := <-handle.WaitCh():
   226  		if res.Successful() {
   227  			t.Fatal("should err")
   228  		}
   229  	case <-time.After(time.Duration(testutil.TestMultiplier()*10) * time.Second):
   230  		t.Fatalf("timeout")
   231  
   232  		// Need to kill long lived process
   233  		if err = handle.Kill(); err != nil {
   234  			t.Fatalf("Error: %s", err)
   235  		}
   236  	}
   237  }
   238  
   239  func TestJavaDriver_Signal(t *testing.T) {
   240  	if !javaLocated() {
   241  		t.Skip("Java not found; skipping")
   242  	}
   243  
   244  	ctestutils.JavaCompatible(t)
   245  	task := &structs.Task{
   246  		Name: "demo-app",
   247  		Config: map[string]interface{}{
   248  			"jar_path": "demoapp.jar",
   249  		},
   250  		LogConfig: &structs.LogConfig{
   251  			MaxFiles:      10,
   252  			MaxFileSizeMB: 10,
   253  		},
   254  		Resources: basicResources,
   255  	}
   256  
   257  	driverCtx, execCtx := testDriverContexts(task)
   258  	defer execCtx.AllocDir.Destroy()
   259  	d := NewJavaDriver(driverCtx)
   260  
   261  	// Copy the test jar into the task's directory
   262  	dst, _ := execCtx.AllocDir.TaskDirs[task.Name]
   263  	copyFile("./test-resources/java/demoapp.jar", filepath.Join(dst, "demoapp.jar"), t)
   264  
   265  	handle, err := d.Start(execCtx, task)
   266  	if err != nil {
   267  		t.Fatalf("err: %v", err)
   268  	}
   269  	if handle == nil {
   270  		t.Fatalf("missing handle")
   271  	}
   272  
   273  	go func() {
   274  		time.Sleep(100 * time.Millisecond)
   275  		err := handle.Signal(syscall.SIGHUP)
   276  		if err != nil {
   277  			t.Fatalf("err: %v", err)
   278  		}
   279  	}()
   280  
   281  	// Task should terminate quickly
   282  	select {
   283  	case res := <-handle.WaitCh():
   284  		if res.Successful() {
   285  			t.Fatal("should err")
   286  		}
   287  	case <-time.After(time.Duration(testutil.TestMultiplier()*10) * time.Second):
   288  		t.Fatalf("timeout")
   289  
   290  		// Need to kill long lived process
   291  		if err = handle.Kill(); err != nil {
   292  			t.Fatalf("Error: %s", err)
   293  		}
   294  	}
   295  }
   296  
   297  func TestJavaDriverUser(t *testing.T) {
   298  	if !javaLocated() {
   299  		t.Skip("Java not found; skipping")
   300  	}
   301  
   302  	ctestutils.JavaCompatible(t)
   303  	task := &structs.Task{
   304  		Name: "demo-app",
   305  		User: "alice",
   306  		Config: map[string]interface{}{
   307  			"jar_path": "demoapp.jar",
   308  		},
   309  		LogConfig: &structs.LogConfig{
   310  			MaxFiles:      10,
   311  			MaxFileSizeMB: 10,
   312  		},
   313  		Resources: basicResources,
   314  	}
   315  
   316  	driverCtx, execCtx := testDriverContexts(task)
   317  	defer execCtx.AllocDir.Destroy()
   318  	d := NewJavaDriver(driverCtx)
   319  
   320  	handle, err := d.Start(execCtx, task)
   321  	if err == nil {
   322  		handle.Kill()
   323  		t.Fatalf("Should've failed")
   324  	}
   325  	msg := "user alice"
   326  	if !strings.Contains(err.Error(), msg) {
   327  		t.Fatalf("Expecting '%v' in '%v'", msg, err)
   328  	}
   329  }