github.com/unirita/cuto@v0.9.8-0.20160830082821-aa6652f877b7/master/jobnet/job_test.go (about)

     1  package jobnet
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/unirita/cuto/db"
    10  	"github.com/unirita/cuto/db/tx"
    11  	"github.com/unirita/cuto/master/config"
    12  	"github.com/unirita/cuto/message"
    13  )
    14  
    15  func newTestNetwork() *Network {
    16  	n, _ := NewNetwork("test")
    17  	n.Result = tx.NewResultMap()
    18  
    19  	dbpath := getTestDBPath()
    20  	conn, err := db.Open(dbpath)
    21  	if err != nil {
    22  		panic(err)
    23  	}
    24  	n.Result.SetConnection(conn)
    25  	return n
    26  }
    27  
    28  func testSendRequest_Normal(host string, port int, reqMsg string, stCh chan<- string) (string, error) {
    29  	req := new(message.Request)
    30  	req.ParseJSON("reqMsg")
    31  
    32  	res := new(message.Response)
    33  	res.NID = req.NID
    34  	res.JID = req.JID
    35  	res.RC = 0
    36  	res.Stat = 1
    37  	res.Detail = ""
    38  	res.Var = "testvar"
    39  	res.St = "2015-04-01 12:34:56.789"
    40  	res.Et = "2015-04-01 12:35:46.123"
    41  
    42  	resMsg, _ := res.GenerateJSON()
    43  	return resMsg, nil
    44  }
    45  
    46  func testSendRequest_Abnormal(host string, port int, reqMsg string, stCh chan<- string) (string, error) {
    47  	req := new(message.Request)
    48  	req.ParseJSON("reqMsg")
    49  
    50  	res := new(message.Response)
    51  	res.NID = req.NID
    52  	res.JID = req.JID
    53  	res.RC = 1
    54  	res.Stat = 9
    55  	res.Detail = "testerror"
    56  	res.Var = "testvar"
    57  	res.St = "2015-04-01 12:34:56.789"
    58  	res.Et = "2015-04-01 12:35:46.123"
    59  
    60  	resMsg, _ := res.GenerateJSON()
    61  	return resMsg, nil
    62  }
    63  
    64  func testSendRequest_Error(host string, port int, reqMsg string, stCh chan<- string) (string, error) {
    65  	return "", fmt.Errorf("senderror")
    66  }
    67  
    68  func testSendRequest_ErrorAfterSt(host string, port int, reqMsg string, stCh chan<- string) (string, error) {
    69  	stCh <- "2015-04-01 12:34:56.789"
    70  	time.Sleep(time.Millisecond * 50)
    71  	return "", fmt.Errorf("senderror")
    72  }
    73  
    74  func testSendRequest_NotJSON(host string, port int, reqMsg string, stCh chan<- string) (string, error) {
    75  	return "notjson", nil
    76  }
    77  
    78  func testSendRequest_Rerun_AllreadyNormalEnd(host string, port int, reqMsg string, stCh chan<- string) (string, error) {
    79  	res := new(message.JobResult)
    80  	res.Stat = db.NORMAL
    81  	resMsg, _ := res.GenerateJSON()
    82  	return resMsg, nil
    83  }
    84  
    85  func TestNewJob_ジョブ構造体にデフォルト値がセットされる(t *testing.T) {
    86  	id := "1234"
    87  	name := "testjob"
    88  
    89  	job, err := NewJob(id, name, nil)
    90  
    91  	if job.id != id {
    92  		t.Errorf("IDとして%sが期待されるのに対し、%sがセットされました。", id, job.id)
    93  	}
    94  	if job.Name != name {
    95  		t.Errorf("ジョブ名として%dが期待されるのに対し、%dがセットされました。", name, job.Name)
    96  	}
    97  	if err != nil {
    98  		t.Errorf("ジョブ名[%v]に禁止文字が使用されていませんが、エラーを返しました。。", name)
    99  	}
   100  }
   101  
   102  func TestNewJob_ジョブ名に禁止文字が含まれるとエラー(t *testing.T) {
   103  	id := "1234"
   104  	name := "te:stjob"
   105  
   106  	_, err := NewJob(id, name, nil)
   107  
   108  	if err == nil {
   109  		t.Errorf("ジョブ名[%v]に禁止文字が組まれているにかかわらず、エラーを返しませんでした。", name)
   110  	}
   111  }
   112  
   113  func TestJobType_ジョブ構造体のノードタイプを取得できる(t *testing.T) {
   114  	id := "1234"
   115  	name := "testjob"
   116  	job, _ := NewJob(id, name, nil)
   117  
   118  	if job.Type() != ELM_JOB {
   119  		t.Errorf("間違ったノードタイプ[%v]が取得された。", job.Type())
   120  	}
   121  }
   122  
   123  func TestJobAddNext_ジョブ構造体に後続エレメントを追加できる(t *testing.T) {
   124  	j1 := new(Job)
   125  	j2 := new(Job)
   126  	g1 := new(Gateway)
   127  
   128  	if err := j1.AddNext(j2); err != nil {
   129  		t.Fatalf("想定外のエラーが発生した: %s", err)
   130  	}
   131  	if j1.Next != j2 {
   132  		t.Error("後続ジョブの追加に失敗した。")
   133  	}
   134  	if err := j2.AddNext(g1); err != nil {
   135  		t.Fatalf("想定外のエラーが発生した: %s", err)
   136  	}
   137  	if j2.Next != g1 {
   138  		t.Error("後続ゲートウェイの追加に失敗した。")
   139  	}
   140  }
   141  
   142  func TestJobAddNext_後続エレメントを複数追加しようとした場合はエラー(t *testing.T) {
   143  	j1 := new(Job)
   144  	j2 := new(Job)
   145  	j3 := new(Job)
   146  	j1.AddNext(j2)
   147  
   148  	if err := j1.AddNext(j3); err == nil {
   149  		t.Error("エラーが発生しなかった。")
   150  	}
   151  }
   152  
   153  func TestJobHasNext_ジョブ構造体の後続エレメントの有無をチェックできる(t *testing.T) {
   154  	j1 := new(Job)
   155  	j2 := new(Job)
   156  	g1 := new(Gateway)
   157  
   158  	if j1.HasNext() {
   159  		t.Error("後続エレメントが無いのにも関わらず、HasNextがtrueを返した")
   160  	}
   161  
   162  	j1.Next = j2
   163  	if !j1.HasNext() {
   164  		t.Error("後続ジョブがあるのにも関わらず、HasNextがfalseを返した")
   165  	}
   166  
   167  	j2.Next = g1
   168  	if !j2.HasNext() {
   169  		t.Error("後続ゲートウェイがあるのにも関わらず、HasNextがfalseを返した")
   170  	}
   171  }
   172  
   173  func TestJobExecute_レスポンスにエラーが無いケース(t *testing.T) {
   174  	config.Job.AttemptLimit = 1
   175  	n := newTestNetwork()
   176  	j1, _ := NewJob("jobid1", "job1", n)
   177  	j2, _ := NewJob("jobid1", "job1", n)
   178  	j1.Node = "testnode"
   179  	j1.Port = 1234
   180  	j1.Next = j2
   181  
   182  	j1.sendRequest = testSendRequest_Normal
   183  	next, err := j1.Execute()
   184  	if err != nil {
   185  		t.Fatalf("想定外のエラーが発生: %s", err)
   186  	}
   187  	if next != j2 {
   188  		t.Errorf("次に実行されるのとは違うノード[%s]が返された。", next.ID())
   189  	}
   190  
   191  	jobres, ok := n.Result.GetJobResults(j1.id)
   192  	if !ok {
   193  		t.Fatal("ジョブ実行結果がセットされなかった。")
   194  	}
   195  	if jobres.ID != n.ID {
   196  		t.Errorf("ジョブ実行結果のID[%d]は想定と違っている。", jobres.ID)
   197  	}
   198  	if jobres.JobId != j1.id {
   199  		t.Errorf("ジョブ実行結果のJobId[%s]は想定と違っている。", jobres.JobId)
   200  	}
   201  	if jobres.JobName != j1.Name {
   202  		t.Errorf("ジョブ実行結果のJobName[%s]は想定と違っている。", jobres.JobName)
   203  	}
   204  	if jobres.StartDate != "2015-04-01 12:34:56.789" {
   205  		t.Errorf("ジョブ実行結果のStartDate[%s]は想定と違っている。", jobres.StartDate)
   206  	}
   207  	if jobres.EndDate != "2015-04-01 12:35:46.123" {
   208  		t.Errorf("ジョブ実行結果のEndDate[%s]は想定と違っている。", jobres.EndDate)
   209  	}
   210  	if jobres.Status != 1 {
   211  		t.Errorf("ジョブ実行結果のStatus[%d]は想定と違っている。", jobres.Status)
   212  	}
   213  	if jobres.Detail != "" {
   214  		t.Errorf("ジョブ実行結果のDetail[%s]は想定と違っている。", jobres.Detail)
   215  	}
   216  	if jobres.Rc != 0 {
   217  		t.Errorf("ジョブ実行結果のRc[%d]は想定と違っている。", jobres.Rc)
   218  	}
   219  	if jobres.Node != "testnode" {
   220  		t.Errorf("ジョブ実行結果のNode[%s]は想定と違っている。", jobres.Node)
   221  	}
   222  	if jobres.Port != 1234 {
   223  		t.Errorf("ジョブ実行結果のPort[%d]は想定と違っている。", jobres.Port)
   224  	}
   225  	if jobres.Variable != "testvar" {
   226  		t.Errorf("ジョブ実行結果のVariable[%s]は想定と違っている。", jobres.Variable)
   227  	}
   228  }
   229  
   230  func TestJobExecute_使用できない変数を使用したケース(t *testing.T) {
   231  	config.Job.AttemptLimit = 1
   232  	n := newTestNetwork()
   233  	j1, _ := NewJob("jobid1", "job1", n)
   234  	j2, _ := NewJob("jobid1", "job1", n)
   235  	j1.Node = "testnode"
   236  	j1.Port = 1234
   237  	j1.Param = "$MJNOEXISTS_RC$"
   238  	j1.Next = j2
   239  
   240  	j1.sendRequest = testSendRequest_Normal
   241  	next, err := j1.Execute()
   242  	if err == nil {
   243  		t.Fatal("エラーが発生しなかった。")
   244  	}
   245  	if next != nil {
   246  		t.Errorf("nilが返される想定に対し、ノード[%s]が返された。", next.ID())
   247  	}
   248  
   249  	jobres, ok := n.Result.GetJobResults(j1.id)
   250  	if !ok {
   251  		t.Fatal("ジョブ実行結果がセットされなかった。")
   252  	}
   253  	if jobres.ID != n.ID {
   254  		t.Errorf("ジョブ実行結果のID[%d]は想定と違っている。", jobres.ID)
   255  	}
   256  	if jobres.JobId != j1.id {
   257  		t.Errorf("ジョブ実行結果のJobId[%s]は想定と違っている。", jobres.JobId)
   258  	}
   259  	if jobres.JobName != j1.Name {
   260  		t.Errorf("ジョブ実行結果のJobName[%s]は想定と違っている。", jobres.JobName)
   261  	}
   262  	if jobres.Status != 9 {
   263  		t.Errorf("ジョブ実行結果のStatus[%d]は想定と違っている。", jobres.Status)
   264  	}
   265  	if jobres.Detail == "" {
   266  		t.Errorf("ジョブ実行結果のDetail[%s]は想定と違っている。", jobres.Detail)
   267  	}
   268  	if jobres.Node != "testnode" {
   269  		t.Errorf("ジョブ実行結果のNode[%s]は想定と違っている。", jobres.Node)
   270  	}
   271  	if jobres.Port != 1234 {
   272  		t.Errorf("ジョブ実行結果のPort[%d]は想定と違っている。", jobres.Port)
   273  	}
   274  }
   275  
   276  func TestJobExecute_ジョブが異常終了したケース(t *testing.T) {
   277  	config.Job.AttemptLimit = 1
   278  	n := newTestNetwork()
   279  	j1, _ := NewJob("jobid1", "job1", n)
   280  	j2, _ := NewJob("jobid1", "job1", n)
   281  	j1.Node = "testnode"
   282  	j1.Port = 1234
   283  	j1.Next = j2
   284  
   285  	j1.sendRequest = testSendRequest_Abnormal
   286  	next, err := j1.Execute()
   287  	if err == nil {
   288  		t.Fatal("エラーが発生しなかった。")
   289  	}
   290  	if next != nil {
   291  		t.Errorf("nilが返される想定に対し、ノード[%s]が返された。", next.ID())
   292  	}
   293  
   294  	jobres, ok := n.Result.GetJobResults(j1.id)
   295  	if !ok {
   296  		t.Fatal("ジョブ実行結果がセットされなかった。")
   297  	}
   298  	if jobres.ID != n.ID {
   299  		t.Errorf("ジョブ実行結果のID[%d]は想定と違っている。", jobres.ID)
   300  	}
   301  	if jobres.JobId != j1.id {
   302  		t.Errorf("ジョブ実行結果のJobId[%s]は想定と違っている。", jobres.JobId)
   303  	}
   304  	if jobres.JobName != j1.Name {
   305  		t.Errorf("ジョブ実行結果のJobName[%s]は想定と違っている。", jobres.JobName)
   306  	}
   307  	if jobres.StartDate != "2015-04-01 12:34:56.789" {
   308  		t.Errorf("ジョブ実行結果のStartDate[%s]は想定と違っている。", jobres.StartDate)
   309  	}
   310  	if jobres.EndDate != "2015-04-01 12:35:46.123" {
   311  		t.Errorf("ジョブ実行結果のEndDate[%s]は想定と違っている。", jobres.EndDate)
   312  	}
   313  	if jobres.Status != 9 {
   314  		t.Errorf("ジョブ実行結果のStatus[%d]は想定と違っている。", jobres.Status)
   315  	}
   316  	if jobres.Detail != "testerror" {
   317  		t.Errorf("ジョブ実行結果のDetail[%s]は想定と違っている。", jobres.Detail)
   318  	}
   319  	if jobres.Rc != 1 {
   320  		t.Errorf("ジョブ実行結果のRc[%d]は想定と違っている。", jobres.Rc)
   321  	}
   322  	if jobres.Node != "testnode" {
   323  		t.Errorf("ジョブ実行結果のNode[%s]は想定と違っている。", jobres.Node)
   324  	}
   325  	if jobres.Port != 1234 {
   326  		t.Errorf("ジョブ実行結果のPort[%d]は想定と違っている。", jobres.Port)
   327  	}
   328  	if jobres.Variable != "testvar" {
   329  		t.Errorf("ジョブ実行結果のVariable[%s]は想定と違っている。", jobres.Variable)
   330  	}
   331  }
   332  
   333  func TestJobExecute_リクエスト送信に失敗したケース(t *testing.T) {
   334  	config.Job.AttemptLimit = 1
   335  	n := newTestNetwork()
   336  	j1, _ := NewJob("jobid1", "job1", n)
   337  	j2, _ := NewJob("jobid1", "job1", n)
   338  	j1.Node = "testnode"
   339  	j1.Port = 1234
   340  	j1.Next = j2
   341  
   342  	j1.sendRequest = testSendRequest_Error
   343  	next, err := j1.Execute()
   344  	if err == nil {
   345  		t.Fatal("エラーが発生しなかった。")
   346  	}
   347  	if next != nil {
   348  		t.Errorf("nilが返される想定に対し、ノード[%s]が返された。", next.ID())
   349  	}
   350  
   351  	jobres, ok := n.Result.GetJobResults(j1.id)
   352  	if !ok {
   353  		t.Fatal("ジョブ実行結果がセットされなかった。")
   354  	}
   355  	if jobres.ID != n.ID {
   356  		t.Errorf("ジョブ実行結果のID[%d]は想定と違っている。", jobres.ID)
   357  	}
   358  	if jobres.JobId != j1.id {
   359  		t.Errorf("ジョブ実行結果のJobId[%s]は想定と違っている。", jobres.JobId)
   360  	}
   361  	if jobres.JobName != j1.Name {
   362  		t.Errorf("ジョブ実行結果のJobName[%s]は想定と違っている。", jobres.JobName)
   363  	}
   364  	if jobres.Status != 9 {
   365  		t.Errorf("ジョブ実行結果のStatus[%d]は想定と違っている。", jobres.Status)
   366  	}
   367  	if jobres.Detail != "senderror" {
   368  		t.Errorf("ジョブ実行結果のDetail[%s]は想定と違っている。", jobres.Detail)
   369  	}
   370  	if jobres.Node != "testnode" {
   371  		t.Errorf("ジョブ実行結果のNode[%s]は想定と違っている。", jobres.Node)
   372  	}
   373  	if jobres.Port != 1234 {
   374  		t.Errorf("ジョブ実行結果のPort[%d]は想定と違っている。", jobres.Port)
   375  	}
   376  }
   377  
   378  func TestJobExecute_リクエスト送信に失敗したケース_失敗前にスタート時刻を受け取った場合(t *testing.T) {
   379  	config.Job.AttemptLimit = 1
   380  	n := newTestNetwork()
   381  	j1, _ := NewJob("jobid1", "job1", n)
   382  	j2, _ := NewJob("jobid1", "job1", n)
   383  	j1.Node = "testnode"
   384  	j1.Port = 1234
   385  	j1.Next = j2
   386  
   387  	j1.sendRequest = testSendRequest_ErrorAfterSt
   388  	next, err := j1.Execute()
   389  	if err == nil {
   390  		t.Fatal("エラーが発生しなかった。")
   391  	}
   392  	if next != nil {
   393  		t.Errorf("nilが返される想定に対し、ノード[%s]が返された。", next.ID())
   394  	}
   395  
   396  	jobres, ok := n.Result.GetJobResults(j1.id)
   397  	if !ok {
   398  		t.Fatal("ジョブ実行結果がセットされなかった。")
   399  	}
   400  	if jobres.ID != n.ID {
   401  		t.Errorf("ジョブ実行結果のID[%d]は想定と違っている。", jobres.ID)
   402  	}
   403  	if jobres.JobId != j1.id {
   404  		t.Errorf("ジョブ実行結果のJobId[%s]は想定と違っている。", jobres.JobId)
   405  	}
   406  	if jobres.JobName != j1.Name {
   407  		t.Errorf("ジョブ実行結果のJobName[%s]は想定と違っている。", jobres.JobName)
   408  	}
   409  	if jobres.StartDate != "2015-04-01 12:34:56.789" {
   410  		t.Errorf("ジョブ実行結果のStartDate[%s]は想定と違っている。", jobres.StartDate)
   411  	}
   412  	if jobres.Status != 9 {
   413  		t.Errorf("ジョブ実行結果のStatus[%d]は想定と違っている。", jobres.Status)
   414  	}
   415  	if jobres.Detail != "senderror" {
   416  		t.Errorf("ジョブ実行結果のDetail[%s]は想定と違っている。", jobres.Detail)
   417  	}
   418  	if jobres.Node != "testnode" {
   419  		t.Errorf("ジョブ実行結果のNode[%s]は想定と違っている。", jobres.Node)
   420  	}
   421  	if jobres.Port != 1234 {
   422  		t.Errorf("ジョブ実行結果のPort[%d]は想定と違っている。", jobres.Port)
   423  	}
   424  }
   425  
   426  func TestJobExecute_レスポンスがJSON形式でないケース(t *testing.T) {
   427  	config.Job.AttemptLimit = 1
   428  	n := newTestNetwork()
   429  	j1, _ := NewJob("jobid1", "job1", n)
   430  	j2, _ := NewJob("jobid1", "job1", n)
   431  	j1.Node = "testnode"
   432  	j1.Port = 1234
   433  	j1.Next = j2
   434  
   435  	j1.sendRequest = testSendRequest_NotJSON
   436  	next, err := j1.Execute()
   437  	if err == nil {
   438  		t.Fatal("エラーが発生しなかった。")
   439  	}
   440  	if next != nil {
   441  		t.Errorf("nilが返される想定に対し、ノード[%s]が返された。", next.ID())
   442  	}
   443  
   444  	jobres, ok := n.Result.GetJobResults(j1.id)
   445  	if !ok {
   446  		t.Fatal("ジョブ実行結果がセットされなかった。")
   447  	}
   448  	if jobres.ID != n.ID {
   449  		t.Errorf("ジョブ実行結果のID[%d]は想定と違っている。", jobres.ID)
   450  	}
   451  	if jobres.JobId != j1.id {
   452  		t.Errorf("ジョブ実行結果のJobId[%s]は想定と違っている。", jobres.JobId)
   453  	}
   454  	if jobres.JobName != j1.Name {
   455  		t.Errorf("ジョブ実行結果のJobName[%s]は想定と違っている。", jobres.JobName)
   456  	}
   457  	if jobres.Status != 9 {
   458  		t.Errorf("ジョブ実行結果のStatus[%d]は想定と違っている。", jobres.Status)
   459  	}
   460  	if jobres.Detail == "" {
   461  		t.Errorf("ジョブ実行結果のDetail[%s]は想定と違っている。", jobres.Detail)
   462  	}
   463  	if jobres.Node != "testnode" {
   464  		t.Errorf("ジョブ実行結果のNode[%s]は想定と違っている。", jobres.Node)
   465  	}
   466  	if jobres.Port != 1234 {
   467  		t.Errorf("ジョブ実行結果のPort[%d]は想定と違っている。", jobres.Port)
   468  	}
   469  }
   470  
   471  func TestJobExecute_リラン実行_DB内の実績が既に正常終了していた場合(t *testing.T) {
   472  	config.Job.AttemptLimit = 1
   473  	n := newTestNetwork()
   474  	n.ID = 1
   475  
   476  	j1, _ := NewJob("jobid1", "job1", n)
   477  	j2, _ := NewJob("jobid1", "job1", n)
   478  	j1.IsRerunJob = true
   479  	j1.Node = "testnode"
   480  	j1.Port = 1234
   481  	j1.Next = j2
   482  
   483  	n.Result.AddJobResults(j1.id, &db.JobResult{Status: db.NORMAL})
   484  
   485  	elm, err := j1.Execute()
   486  	if err != nil {
   487  		t.Errorf("想定外のエラーが発生した: %s", err)
   488  	}
   489  	if elm != j2 {
   490  		t.Error("次のジョブが返されていない。")
   491  	}
   492  }
   493  
   494  func TestJobExecute_リラン実行_リモートの実行結果が既に正常終了していた場合(t *testing.T) {
   495  	config.Job.AttemptLimit = 1
   496  	n := newTestNetwork()
   497  	n.ID = 1
   498  
   499  	j1, _ := NewJob("jobid1", "job1", n)
   500  	j2, _ := NewJob("jobid1", "job1", n)
   501  	j1.sendRequest = testSendRequest_Rerun_AllreadyNormalEnd
   502  	j1.IsRerunJob = true
   503  	j1.Node = "testnode"
   504  	j1.Port = 1234
   505  	j1.Next = j2
   506  
   507  	n.Result.AddJobResults(j1.id, &db.JobResult{Status: db.ABNORMAL})
   508  
   509  	elm, err := j1.Execute()
   510  	if err != nil {
   511  		t.Errorf("想定外のエラーが発生した: %s", err)
   512  	}
   513  	if elm != j2 {
   514  		t.Error("次のジョブが返されていない。")
   515  	}
   516  }
   517  
   518  func TestCreateJoblogFileName(t *testing.T) {
   519  	n := newTestNetwork()
   520  	j, _ := NewJob("jobid1", "job1", n)
   521  	j.FilePath = `C:\test\testjob.bat`
   522  
   523  	res := new(message.Response)
   524  	res.NID = n.ID
   525  	res.JID = j.ID()
   526  	res.RC = 1
   527  	res.Stat = 9
   528  	res.Detail = "testerror"
   529  	res.Var = "testvar"
   530  	res.St = "2015-04-01 12:34:56.789"
   531  	res.Et = "2015-04-01 12:35:46.123"
   532  
   533  	actual := j.createJoblogFileName(res)
   534  	expected := strconv.Itoa(n.ID) + `.testjob.jobid1.20150401123456.789.log`
   535  	if actual != expected {
   536  		t.Errorf("ジョブログファイル名[%s]は想定値[%s]と違っている。", actual, expected)
   537  	}
   538  }
   539  
   540  func TestCreateRequest_NotContainerJob(t *testing.T) {
   541  	n := &Network{ID: 1234}
   542  	j, err := NewJob("j1", "testjob", n)
   543  	if err != nil {
   544  		t.Fatal("Unexpected error:", err)
   545  	}
   546  	j.Node = "testnode"
   547  	j.FilePath = "/path/to/test.sh"
   548  	j.Param = "param1 param2"
   549  	j.Env = "ENAME1=EVAL1+ENAME2=EVAL2"
   550  	j.Workspace = "/path/to/workspace"
   551  	j.WrnRC = 5
   552  	j.WrnPtn = "warning"
   553  	j.ErrRC = 10
   554  	j.ErrPtn = "error"
   555  	j.Timeout = 100
   556  
   557  	req := j.createRequest()
   558  	if req.NID != 1234 {
   559  		t.Errorf("req.NID => %d, wants %d", req.NID, 1234)
   560  	}
   561  	if req.JID != "j1" {
   562  		t.Errorf("req.JID => %s, wants %s", req.JID, "j1")
   563  	}
   564  	if req.Path != j.FilePath {
   565  		t.Errorf("req.Path => %s, wants %s", req.Path, j.FilePath)
   566  	}
   567  	if req.Param != j.Param {
   568  		t.Errorf("req.Param => %s, wants %s", req.Param, j.Param)
   569  	}
   570  	if req.Env != j.Env {
   571  		t.Errorf("req.Env => %s, wants %s", req.Env, j.Env)
   572  	}
   573  	if req.Workspace != j.Workspace {
   574  		t.Errorf("req.Workspace => %s, wants %s", req.Workspace, j.Workspace)
   575  	}
   576  	if req.WarnRC != j.WrnRC {
   577  		t.Errorf("req.WarnRC => %d, wants %d", req.WarnRC, j.WrnRC)
   578  	}
   579  	if req.WarnStr != j.WrnPtn {
   580  		t.Errorf("req.WarnStr => %s, wants %s", req.WarnStr, j.WrnPtn)
   581  	}
   582  	if req.ErrRC != j.ErrRC {
   583  		t.Errorf("req.ErrRC => %d, wants %d", req.ErrRC, j.ErrRC)
   584  	}
   585  	if req.ErrStr != j.ErrPtn {
   586  		t.Errorf("req.ErrStr => %s, wants %s", req.ErrStr, j.ErrPtn)
   587  	}
   588  	if req.Timeout != j.Timeout {
   589  		t.Errorf("req.Timeout => %d, wants %d", req.Timeout, j.Timeout)
   590  	}
   591  }
   592  
   593  func TestCreateRequest_ContainerJob(t *testing.T) {
   594  	n := &Network{ID: 1234}
   595  	j, err := NewJob("j1", "testjob", n)
   596  	if err != nil {
   597  		t.Fatal("Unexpected error:", err)
   598  	}
   599  	j.Node = "testhost>container"
   600  	j.FilePath = "/path/to/test.sh"
   601  	j.Param = "param1 param2"
   602  
   603  	req := j.createRequest()
   604  	if req.Path != message.DockerTag {
   605  		t.Errorf("req.Path => %s, wants %s", req.Path, message.DockerTag)
   606  	}
   607  	if req.Param != "exec container /path/to/test.sh param1 param2" {
   608  		t.Errorf("req.Param => %s, wants %s", req.Param, "exec container /path/to/test.sh param1 param2")
   609  	}
   610  }
   611  
   612  func TestCreateRequest_ContainerJobWithHost(t *testing.T) {
   613  	n := &Network{ID: 1234}
   614  	j, err := NewJob("j1", "testjob", n)
   615  	if err != nil {
   616  		t.Fatal("Unexpected error:", err)
   617  	}
   618  	j.Node = "testhost>tcp://host/container"
   619  	j.FilePath = "/path/to/test.sh"
   620  	j.Param = "param1 param2"
   621  
   622  	req := j.createRequest()
   623  	if req.Path != message.DockerTag {
   624  		t.Errorf("req.Path => %s, wants %s", req.Path, message.DockerTag)
   625  	}
   626  	if req.Param != "-H=tcp://host exec container /path/to/test.sh param1 param2" {
   627  		t.Errorf("req.Param => %s, wants %s", req.Param, "-H=tcp://host exec container /path/to/test.sh param1 param2")
   628  	}
   629  }
   630  
   631  func TestExplodeNodeString_NoContainer(t *testing.T) {
   632  	node := "testhost"
   633  	host, containerHost, containerName := explodeNodeString(node)
   634  	if host != "testhost" {
   635  		t.Errorf("host => %s, wants %s", host, "testhost")
   636  	}
   637  	if containerHost != "" {
   638  		t.Error("containerHost must be empty, but it was not.")
   639  		t.Log("containerHost:", containerHost)
   640  	}
   641  	if containerName != "" {
   642  		t.Error("containerName must be empty, but it was not.")
   643  		t.Log("containerName:", containerName)
   644  	}
   645  }
   646  
   647  func TestExplodeNodeString_ContainerWithoutHost(t *testing.T) {
   648  	node := "testhost>category/name"
   649  	host, containerHost, containerName := explodeNodeString(node)
   650  	if host != "testhost" {
   651  		t.Errorf("host => %s, wants %s", host, "testhost")
   652  	}
   653  	if containerHost != "" {
   654  		t.Error("containerHost must be empty, but it was not.")
   655  		t.Log("containerHost:", containerHost)
   656  	}
   657  	if containerName != "category/name" {
   658  		t.Errorf("containerName => %s, wants %s", containerName, "category/name")
   659  	}
   660  }
   661  
   662  func TestExplodeNodeString_ContainerWithHost(t *testing.T) {
   663  	node := "testhost>tcp://hostname/category/name"
   664  	host, containerHost, containerName := explodeNodeString(node)
   665  	if host != "testhost" {
   666  		t.Errorf("host => %s, wants %s", host, "testhost")
   667  	}
   668  	if containerHost != "tcp://hostname" {
   669  		t.Errorf("containerHost => %s, wants %s", containerHost, "tcp://hostname")
   670  	}
   671  	if containerName != "category/name" {
   672  		t.Errorf("containerName => %s, wants %s", containerName, "category/name")
   673  	}
   674  }
   675  
   676  func TestUseSecondNode(t *testing.T) {
   677  	n := newTestNetwork()
   678  
   679  	j1, _ := NewJob("jobid1", "job1", n)
   680  	j1.IsRerunJob = true
   681  	j1.Node = "testnode"
   682  	j1.Port = 1234
   683  	j1.SecondaryNode = "secondarynode"
   684  	j1.SecondaryPort = 2345
   685  
   686  	n.Result.AddJobResults(j1.id, &db.JobResult{})
   687  
   688  	j1.useSecondaryNode()
   689  	if j1.Node != "secondarynode" {
   690  		t.Errorf("j1.Node => %s, wants %s", j1.Node, "secondarynode")
   691  	}
   692  	if j1.Port != 2345 {
   693  		t.Errorf("j1.Port => %d, wants %d", j1.Port, 2345)
   694  	}
   695  	if j1.SecondaryNode != "" {
   696  		t.Error("j1.SecondaryNode must be empty, but it was not.")
   697  	}
   698  	if j1.SecondaryPort != 0 {
   699  		t.Errorf("j1.SecondaryPort => %d, wants %d", j1.SecondaryPort, 0)
   700  	}
   701  }