github.com/ranjib/nomad@v0.1.1-0.20160225204057-97751b02f70b/client/driver/executor/executor_test.go (about)

     1  package executor
     2  
     3  import (
     4  	"io/ioutil"
     5  	"log"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/hashicorp/nomad/client/allocdir"
    13  	"github.com/hashicorp/nomad/client/driver/env"
    14  	"github.com/hashicorp/nomad/client/testutil"
    15  	"github.com/hashicorp/nomad/nomad/mock"
    16  	"github.com/hashicorp/nomad/nomad/structs"
    17  	tu "github.com/hashicorp/nomad/testutil"
    18  )
    19  
    20  var (
    21  	constraint = &structs.Resources{
    22  		CPU:      250,
    23  		MemoryMB: 256,
    24  		Networks: []*structs.NetworkResource{
    25  			&structs.NetworkResource{
    26  				MBits:        50,
    27  				DynamicPorts: []structs.Port{{Label: "http"}},
    28  			},
    29  		},
    30  	}
    31  )
    32  
    33  func mockAllocDir(t *testing.T) (string, *allocdir.AllocDir) {
    34  	alloc := mock.Alloc()
    35  	task := alloc.Job.TaskGroups[0].Tasks[0]
    36  
    37  	allocDir := allocdir.NewAllocDir(filepath.Join(os.TempDir(), alloc.ID))
    38  	if err := allocDir.Build([]*structs.Task{task}); err != nil {
    39  		log.Panicf("allocDir.Build() failed: %v", err)
    40  	}
    41  
    42  	return task.Name, allocDir
    43  }
    44  
    45  func testExecutorContext(t *testing.T) *ExecutorContext {
    46  	taskEnv := env.NewTaskEnvironment(mock.Node())
    47  	taskName, allocDir := mockAllocDir(t)
    48  	ctx := &ExecutorContext{
    49  		TaskEnv:       taskEnv,
    50  		TaskName:      taskName,
    51  		AllocDir:      allocDir,
    52  		TaskResources: constraint,
    53  		LogConfig:     structs.DefaultLogConfig(),
    54  	}
    55  	return ctx
    56  }
    57  
    58  func TestExecutor_Start_Invalid(t *testing.T) {
    59  	invalid := "/bin/foobar"
    60  	execCmd := ExecCommand{Cmd: invalid, Args: []string{"1"}}
    61  	ctx := testExecutorContext(t)
    62  	defer ctx.AllocDir.Destroy()
    63  	executor := NewExecutor(log.New(os.Stdout, "", log.LstdFlags))
    64  	_, err := executor.LaunchCmd(&execCmd, ctx)
    65  	if err == nil {
    66  		t.Fatalf("Expected error")
    67  	}
    68  }
    69  
    70  func TestExecutor_Start_Wait_Failure_Code(t *testing.T) {
    71  	execCmd := ExecCommand{Cmd: "/bin/sleep", Args: []string{"fail"}}
    72  	ctx := testExecutorContext(t)
    73  	defer ctx.AllocDir.Destroy()
    74  	executor := NewExecutor(log.New(os.Stdout, "", log.LstdFlags))
    75  	ps, _ := executor.LaunchCmd(&execCmd, ctx)
    76  	if ps.Pid == 0 {
    77  		t.Fatalf("expected process to start and have non zero pid")
    78  	}
    79  	ps, _ = executor.Wait()
    80  	if ps.ExitCode < 1 {
    81  		t.Fatalf("expected exit code to be non zero, actual: %v", ps.ExitCode)
    82  	}
    83  }
    84  
    85  func TestExecutor_Start_Wait(t *testing.T) {
    86  	execCmd := ExecCommand{Cmd: "/bin/echo", Args: []string{"hello world"}}
    87  	ctx := testExecutorContext(t)
    88  	defer ctx.AllocDir.Destroy()
    89  	executor := NewExecutor(log.New(os.Stdout, "", log.LstdFlags))
    90  	ps, err := executor.LaunchCmd(&execCmd, ctx)
    91  	if err != nil {
    92  		t.Fatalf("error in launching command: %v", err)
    93  	}
    94  	if ps.Pid == 0 {
    95  		t.Fatalf("expected process to start and have non zero pid")
    96  	}
    97  	ps, err = executor.Wait()
    98  	if err != nil {
    99  		t.Fatalf("error in waiting for command: %v", err)
   100  	}
   101  
   102  	expected := "hello world"
   103  	file := filepath.Join(ctx.AllocDir.LogDir(), "web.stdout.0")
   104  	output, err := ioutil.ReadFile(file)
   105  	if err != nil {
   106  		t.Fatalf("Couldn't read file %v", file)
   107  	}
   108  
   109  	act := strings.TrimSpace(string(output))
   110  	if act != expected {
   111  		t.Fatalf("Command output incorrectly: want %v; got %v", expected, act)
   112  	}
   113  }
   114  
   115  func TestExecutor_IsolationAndConstraints(t *testing.T) {
   116  	testutil.ExecCompatible(t)
   117  
   118  	execCmd := ExecCommand{Cmd: "/bin/echo", Args: []string{"hello world"}}
   119  	ctx := testExecutorContext(t)
   120  	defer ctx.AllocDir.Destroy()
   121  
   122  	ctx.FSIsolation = true
   123  	ctx.ResourceLimits = true
   124  	ctx.UnprivilegedUser = true
   125  
   126  	executor := NewExecutor(log.New(os.Stdout, "", log.LstdFlags))
   127  	ps, err := executor.LaunchCmd(&execCmd, ctx)
   128  	if err != nil {
   129  		t.Fatalf("error in launching command: %v", err)
   130  	}
   131  	if ps.Pid == 0 {
   132  		t.Fatalf("expected process to start and have non zero pid")
   133  	}
   134  	ps, err = executor.Wait()
   135  	if err != nil {
   136  		t.Fatalf("error in waiting for command: %v", err)
   137  	}
   138  
   139  	expected := "hello world"
   140  	file := filepath.Join(ctx.AllocDir.LogDir(), "web.stdout.0")
   141  	output, err := ioutil.ReadFile(file)
   142  	if err != nil {
   143  		t.Fatalf("Couldn't read file %v", file)
   144  	}
   145  
   146  	act := strings.TrimSpace(string(output))
   147  	if act != expected {
   148  		t.Fatalf("Command output incorrectly: want %v; got %v", expected, act)
   149  	}
   150  }
   151  
   152  func TestExecutor_Start_Kill(t *testing.T) {
   153  	execCmd := ExecCommand{Cmd: "/bin/sleep", Args: []string{"10 && hello world"}}
   154  	ctx := testExecutorContext(t)
   155  	defer ctx.AllocDir.Destroy()
   156  	executor := NewExecutor(log.New(os.Stdout, "", log.LstdFlags))
   157  	ps, err := executor.LaunchCmd(&execCmd, ctx)
   158  	if err != nil {
   159  		t.Fatalf("error in launching command: %v", err)
   160  	}
   161  	if ps.Pid == 0 {
   162  		t.Fatalf("expected process to start and have non zero pid")
   163  	}
   164  	ps, err = executor.Wait()
   165  	if err != nil {
   166  		t.Fatalf("error in waiting for command: %v", err)
   167  	}
   168  
   169  	file := filepath.Join(ctx.AllocDir.LogDir(), "web.stdout.0")
   170  	time.Sleep(time.Duration(tu.TestMultiplier()*2) * time.Second)
   171  
   172  	output, err := ioutil.ReadFile(file)
   173  	if err != nil {
   174  		t.Fatalf("Couldn't read file %v", file)
   175  	}
   176  
   177  	expected := ""
   178  	act := strings.TrimSpace(string(output))
   179  	if act != expected {
   180  		t.Fatalf("Command output incorrectly: want %v; got %v", expected, act)
   181  	}
   182  }