X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/f15a9a1ad40f589d3c40f856a95e1d5556ee7ca1..b0e6c00576257cef24cfd0599073f58904a2b85c:/sdk/go/crunchrunner/crunchrunner_test.go diff --git a/sdk/go/crunchrunner/crunchrunner_test.go b/sdk/go/crunchrunner/crunchrunner_test.go index 127c434bc9..f4c8193696 100644 --- a/sdk/go/crunchrunner/crunchrunner_test.go +++ b/sdk/go/crunchrunner/crunchrunner_test.go @@ -3,9 +3,13 @@ package main import ( "git.curoverse.com/arvados.git/sdk/go/arvadosclient" . "gopkg.in/check.v1" + "io" "io/ioutil" + "log" "os" + "syscall" "testing" + "time" ) // Gocheck boilerplate @@ -19,136 +23,171 @@ type TestSuite struct{} var _ = Suite(&TestSuite{}) type ArvTestClient struct { + c *C + manifest string + success bool } func (t ArvTestClient) Create(resourceType string, parameters arvadosclient.Dict, output interface{}) error { return nil } -func (t ArvTestClient) Delete(resource string, uuid string, parameters arvadosclient.Dict, output interface{}) (err error) { - return nil -} - func (t ArvTestClient) Update(resourceType string, uuid string, parameters arvadosclient.Dict, output interface{}) (err error) { - return nil -} - -func (t ArvTestClient) Get(resourceType string, uuid string, parameters arvadosclient.Dict, output interface{}) (err error) { - return nil -} - -func (t ArvTestClient) List(resource string, parameters arvadosclient.Dict, output interface{}) (err error) { + t.c.Check(resourceType, Equals, "job_tasks") + t.c.Check(parameters, DeepEquals, arvadosclient.Dict{"job_task": Task{ + Output: t.manifest, + Success: t.success, + Progress: 1}}) return nil } func (s *TestSuite) TestSimpleRun(c *C) { - - api := ArvTestClient{} - tmpdir, _ := ioutil.TempDir("", "") defer func() { os.RemoveAll(tmpdir) }() - err := runner(api, + err := runner(ArvTestClient{c, "", true}, + KeepTestClient{}, "zzzz-8i9sb-111111111111111", "zzzz-ot0gb-111111111111111", tmpdir, "", - Job{script_parameters: Tasks{[]TaskDef{TaskDef{ - commands: []string{"echo", "foo"}}}}}, - Task{sequence: 0}) + Job{Script_parameters: Tasks{[]TaskDef{{ + Command: []string{"echo", "foo"}}}}}, + Task{Sequence: 0}) c.Check(err, IsNil) - } func checkOutput(c *C, tmpdir string) { - file, err := os.Open(tmpdir + "/" + "outdir/output.txt") + file, err := os.Open(tmpdir + "/outdir/output.txt") c.Assert(err, IsNil) data := make([]byte, 100) var count int - count, err = file.Read(data) - c.Assert(err, IsNil) - c.Check(string(data[0:count]), Equals, "foo\n") + err = nil + offset := 0 + for err == nil { + count, err = file.Read(data[offset:]) + offset += count + } + c.Assert(err, Equals, io.EOF) + c.Check(string(data[0:offset]), Equals, "foo\n") } func (s *TestSuite) TestSimpleRunSubtask(c *C) { - - api := ArvTestClient{} - tmpdir, _ := ioutil.TempDir("", "") defer func() { os.RemoveAll(tmpdir) }() - err := runner(api, + err := runner(ArvTestClient{c, + ". d3b07384d113edec49eaa6238ad5ff00+4 0:4:output.txt\n", true}, + KeepTestClient{}, "zzzz-8i9sb-111111111111111", "zzzz-ot0gb-111111111111111", tmpdir, "", - Job{script_parameters: Tasks{[]TaskDef{ - TaskDef{commands: []string{"echo", "bar"}}, - TaskDef{commands: []string{"echo", "foo"}}}}}, - Task{parameters: TaskDef{ - commands: []string{"echo", "foo"}, - stdout: "output.txt"}, - sequence: 1}) + Job{Script_parameters: Tasks{[]TaskDef{ + {Command: []string{"echo", "bar"}}, + {Command: []string{"echo", "foo"}}}}}, + Task{Parameters: TaskDef{ + Command: []string{"echo", "foo"}, + Stdout: "output.txt"}, + Sequence: 1}) c.Check(err, IsNil) checkOutput(c, tmpdir) } func (s *TestSuite) TestRedirect(c *C) { - - api := ArvTestClient{} - tmpfile, _ := ioutil.TempFile("", "") tmpfile.Write([]byte("foo\n")) - tmpfile.Sync() - defer tmpfile.Close() + tmpfile.Close() + defer os.Remove(tmpfile.Name()) tmpdir, _ := ioutil.TempDir("", "") defer func() { os.RemoveAll(tmpdir) }() - err := runner(api, + err := runner(ArvTestClient{c, + ". d3b07384d113edec49eaa6238ad5ff00+4 0:4:output.txt\n", true}, + KeepTestClient{}, "zzzz-8i9sb-111111111111111", "zzzz-ot0gb-111111111111111", tmpdir, "", - Job{script_parameters: Tasks{[]TaskDef{TaskDef{ - commands: []string{"cat"}, - stdout: "output.txt", - stdin: tmpfile.Name()}}}}, - Task{sequence: 0}) + Job{Script_parameters: Tasks{[]TaskDef{{ + Command: []string{"cat"}, + Stdout: "output.txt", + Stdin: tmpfile.Name()}}}}, + Task{Sequence: 0}) c.Check(err, IsNil) checkOutput(c, tmpdir) } func (s *TestSuite) TestEnv(c *C) { + tmpdir, _ := ioutil.TempDir("", "") + defer func() { + os.RemoveAll(tmpdir) + }() + + err := runner(ArvTestClient{c, ". d3b07384d113edec49eaa6238ad5ff00+4 0:4:output.txt\n", true}, + KeepTestClient{}, + "zzzz-8i9sb-111111111111111", + "zzzz-ot0gb-111111111111111", + tmpdir, + "", + Job{Script_parameters: Tasks{[]TaskDef{{ + Command: []string{"/bin/sh", "-c", "echo $BAR"}, + Stdout: "output.txt", + Env: map[string]string{"BAR": "foo"}}}}}, + Task{Sequence: 0}) + c.Check(err, IsNil) + checkOutput(c, tmpdir) +} - api := ArvTestClient{} +func (s *TestSuite) TestEnvSubstitute(c *C) { + tmpdir, _ := ioutil.TempDir("", "") + defer func() { + os.RemoveAll(tmpdir) + }() + err := runner(ArvTestClient{c, ". d3b07384d113edec49eaa6238ad5ff00+4 0:4:output.txt\n", true}, + KeepTestClient{}, + "zzzz-8i9sb-111111111111111", + "zzzz-ot0gb-111111111111111", + tmpdir, + "foo\n", + Job{Script_parameters: Tasks{[]TaskDef{{ + Command: []string{"/bin/sh", "-c", "echo $BAR"}, + Stdout: "output.txt", + Env: map[string]string{"BAR": "$(task.keep)"}}}}}, + Task{Sequence: 0}) + c.Check(err, IsNil) + checkOutput(c, tmpdir) +} + +func (s *TestSuite) TestEnvReplace(c *C) { tmpdir, _ := ioutil.TempDir("", "") defer func() { os.RemoveAll(tmpdir) }() - err := runner(api, + err := runner(ArvTestClient{c, ". d3b07384d113edec49eaa6238ad5ff00+4 0:4:output.txt\n", true}, + KeepTestClient{}, "zzzz-8i9sb-111111111111111", "zzzz-ot0gb-111111111111111", tmpdir, "", - Job{script_parameters: Tasks{[]TaskDef{TaskDef{ - commands: []string{"/bin/sh", "-c", "echo $BAR"}, - stdout: "output.txt", - env: map[string]string{"BAR": "foo"}}}}}, - Task{sequence: 0}) + Job{Script_parameters: Tasks{[]TaskDef{{ + Command: []string{"/bin/sh", "-c", "echo $PATH"}, + Stdout: "output.txt", + Env: map[string]string{"PATH": "foo"}}}}}, + Task{Sequence: 0}) c.Check(err, IsNil) - checkOutput(c, tmpdir) } @@ -165,51 +204,270 @@ func (t *SubtaskTestClient) Create(resourceType string, parameters arvadosclient return nil } -func (t SubtaskTestClient) Delete(resource string, uuid string, parameters arvadosclient.Dict, output interface{}) (err error) { +func (t SubtaskTestClient) Update(resourceType string, uuid string, parameters arvadosclient.Dict, output interface{}) (err error) { return nil } -func (t SubtaskTestClient) Update(resourceType string, uuid string, parameters arvadosclient.Dict, output interface{}) (err error) { - return nil +func (s *TestSuite) TestScheduleSubtask(c *C) { + + api := SubtaskTestClient{c, []Task{ + {Job_uuid: "zzzz-8i9sb-111111111111111", + Created_by_job_task_uuid: "zzzz-ot0gb-111111111111111", + Sequence: 1, + Parameters: TaskDef{ + Command: []string{"echo", "bar"}}}, + {Job_uuid: "zzzz-8i9sb-111111111111111", + Created_by_job_task_uuid: "zzzz-ot0gb-111111111111111", + Sequence: 1, + Parameters: TaskDef{ + Command: []string{"echo", "foo"}}}}, + 0} + + tmpdir, _ := ioutil.TempDir("", "") + defer func() { + os.RemoveAll(tmpdir) + }() + + err := runner(&api, KeepTestClient{}, + "zzzz-8i9sb-111111111111111", + "zzzz-ot0gb-111111111111111", + tmpdir, + "", + Job{Script_parameters: Tasks{[]TaskDef{ + {Command: []string{"echo", "bar"}}, + {Command: []string{"echo", "foo"}}}}}, + Task{Sequence: 0}) + c.Check(err, IsNil) + } -func (t SubtaskTestClient) Get(resourceType string, uuid string, parameters arvadosclient.Dict, output interface{}) (err error) { - return nil +func (s *TestSuite) TestRunFail(c *C) { + tmpdir, _ := ioutil.TempDir("", "") + defer func() { + os.RemoveAll(tmpdir) + }() + + err := runner(ArvTestClient{c, "", false}, KeepTestClient{}, + "zzzz-8i9sb-111111111111111", + "zzzz-ot0gb-111111111111111", + tmpdir, + "", + Job{Script_parameters: Tasks{[]TaskDef{{ + Command: []string{"/bin/sh", "-c", "exit 1"}}}}}, + Task{Sequence: 0}) + c.Check(err, FitsTypeOf, PermFail{}) } -func (t SubtaskTestClient) List(resource string, parameters arvadosclient.Dict, output interface{}) (err error) { - return nil +func (s *TestSuite) TestRunSuccessCode(c *C) { + tmpdir, _ := ioutil.TempDir("", "") + defer func() { + os.RemoveAll(tmpdir) + }() + + err := runner(ArvTestClient{c, "", true}, KeepTestClient{}, + "zzzz-8i9sb-111111111111111", + "zzzz-ot0gb-111111111111111", + tmpdir, + "", + Job{Script_parameters: Tasks{[]TaskDef{{ + Command: []string{"/bin/sh", "-c", "exit 1"}, + SuccessCodes: []int{0, 1}}}}}, + Task{Sequence: 0}) + c.Check(err, IsNil) } -func (s *TestSuite) TestScheduleSubtask(c *C) { +func (s *TestSuite) TestRunFailCode(c *C) { + tmpdir, _ := ioutil.TempDir("", "") + defer func() { + os.RemoveAll(tmpdir) + }() - api := SubtaskTestClient{c, []Task{ - Task{job_uuid: "zzzz-8i9sb-111111111111111", - created_by_job_task_uuid: "zzzz-ot0gb-111111111111111", - sequence: 1, - parameters: TaskDef{ - commands: []string{"echo", "bar"}}}, - Task{job_uuid: "zzzz-8i9sb-111111111111111", - created_by_job_task_uuid: "zzzz-ot0gb-111111111111111", - sequence: 1, - parameters: TaskDef{ - commands: []string{"echo", "foo"}}}}, - 0} + err := runner(ArvTestClient{c, "", false}, KeepTestClient{}, + "zzzz-8i9sb-111111111111111", + "zzzz-ot0gb-111111111111111", + tmpdir, + "", + Job{Script_parameters: Tasks{[]TaskDef{{ + Command: []string{"/bin/sh", "-c", "exit 0"}, + PermanentFailCodes: []int{0, 1}}}}}, + Task{Sequence: 0}) + c.Check(err, FitsTypeOf, PermFail{}) +} + +func (s *TestSuite) TestRunTempFailCode(c *C) { + tmpdir, _ := ioutil.TempDir("", "") + defer func() { + os.RemoveAll(tmpdir) + }() + + err := runner(ArvTestClient{c, "", false}, KeepTestClient{}, + "zzzz-8i9sb-111111111111111", + "zzzz-ot0gb-111111111111111", + tmpdir, + "", + Job{Script_parameters: Tasks{[]TaskDef{{ + Command: []string{"/bin/sh", "-c", "exit 1"}, + TemporaryFailCodes: []int{1}}}}}, + Task{Sequence: 0}) + c.Check(err, FitsTypeOf, TempFail{}) +} + +func (s *TestSuite) TestVwd(c *C) { + tmpfile, _ := ioutil.TempFile("", "") + tmpfile.Write([]byte("foo\n")) + tmpfile.Close() + defer os.Remove(tmpfile.Name()) + + tmpdir, _ := ioutil.TempDir("", "") + defer func() { + os.RemoveAll(tmpdir) + }() + + err := runner(ArvTestClient{c, ". d3b07384d113edec49eaa6238ad5ff00+4 0:4:output.txt\n", true}, + KeepTestClient{}, + "zzzz-8i9sb-111111111111111", + "zzzz-ot0gb-111111111111111", + tmpdir, + "", + Job{Script_parameters: Tasks{[]TaskDef{{ + Command: []string{"ls", "output.txt"}, + Vwd: map[string]string{ + "output.txt": tmpfile.Name()}}}}}, + Task{Sequence: 0}) + c.Check(err, IsNil) + checkOutput(c, tmpdir) +} + +func (s *TestSuite) TestSubstitutionStdin(c *C) { + keepmount, _ := ioutil.TempDir("", "") + ioutil.WriteFile(keepmount+"/"+"file1.txt", []byte("foo\n"), 0600) + defer func() { + os.RemoveAll(keepmount) + }() + + log.Print("Keepmount is ", keepmount) tmpdir, _ := ioutil.TempDir("", "") defer func() { os.RemoveAll(tmpdir) }() - err := runner(&api, + log.Print("tmpdir is ", tmpdir) + + err := runner(ArvTestClient{c, + ". d3b07384d113edec49eaa6238ad5ff00+4 0:4:output.txt\n", true}, + KeepTestClient{}, + "zzzz-8i9sb-111111111111111", + "zzzz-ot0gb-111111111111111", + tmpdir, + keepmount, + Job{Script_parameters: Tasks{[]TaskDef{{ + Command: []string{"cat"}, + Stdout: "output.txt", + Stdin: "$(task.keep)/file1.txt"}}}}, + Task{Sequence: 0}) + c.Check(err, IsNil) + checkOutput(c, tmpdir) +} + +func (s *TestSuite) TestSubstitutionCommandLine(c *C) { + keepmount, _ := ioutil.TempDir("", "") + ioutil.WriteFile(keepmount+"/"+"file1.txt", []byte("foo\n"), 0600) + defer func() { + os.RemoveAll(keepmount) + }() + + tmpdir, _ := ioutil.TempDir("", "") + defer func() { + os.RemoveAll(tmpdir) + }() + + err := runner(ArvTestClient{c, + ". d3b07384d113edec49eaa6238ad5ff00+4 0:4:output.txt\n", true}, + KeepTestClient{}, + "zzzz-8i9sb-111111111111111", + "zzzz-ot0gb-111111111111111", + tmpdir, + keepmount, + Job{Script_parameters: Tasks{[]TaskDef{{ + Command: []string{"cat", "$(task.keep)/file1.txt"}, + Stdout: "output.txt"}}}}, + Task{Sequence: 0}) + c.Check(err, IsNil) + + checkOutput(c, tmpdir) +} + +func (s *TestSuite) TestSignal(c *C) { + tmpdir, _ := ioutil.TempDir("", "") + defer func() { + os.RemoveAll(tmpdir) + }() + + go func() { + time.Sleep(1 * time.Second) + self, _ := os.FindProcess(os.Getpid()) + self.Signal(syscall.SIGINT) + }() + + err := runner(ArvTestClient{c, + "", false}, + KeepTestClient{}, + "zzzz-8i9sb-111111111111111", + "zzzz-ot0gb-111111111111111", + tmpdir, + "", + Job{Script_parameters: Tasks{[]TaskDef{{ + Command: []string{"sleep", "4"}}}}}, + Task{Sequence: 0}) + c.Check(err, FitsTypeOf, PermFail{}) + +} + +func (s *TestSuite) TestQuoting(c *C) { + tmpdir, _ := ioutil.TempDir("", "") + defer func() { + os.RemoveAll(tmpdir) + }() + + err := runner(ArvTestClient{c, + "./s\\040ub:dir d3b07384d113edec49eaa6238ad5ff00+4 0:4::e\\040vil\n", true}, + KeepTestClient{}, + "zzzz-8i9sb-111111111111111", + "zzzz-ot0gb-111111111111111", + tmpdir, + "", + Job{Script_parameters: Tasks{[]TaskDef{{ + Command: []string{"echo", "foo"}, + Stdout: "s ub:dir/:e vi\nl"}}}}, + Task{Sequence: 0}) + c.Check(err, IsNil) +} + +func (s *TestSuite) TestKeepTmp(c *C) { + tmpdir, _ := ioutil.TempDir("", "") + defer func() { + os.RemoveAll(tmpdir) + }() + + os.Setenv("TASK_KEEPMOUNT_TMP", tmpdir) + defer os.Setenv("TASK_KEEPMOUNT_TMP", "") + + fn, err := os.Create(tmpdir + "/.arvados#collection") + fn.Write([]byte("{\"manifest_text\":\". unparsed 0:3:foo\\n\",\"uuid\":null}")) + defer fn.Close() + + err = runner(ArvTestClient{c, + ". unparsed 0:3:foo\n", true}, + KeepTestClient{}, "zzzz-8i9sb-111111111111111", "zzzz-ot0gb-111111111111111", tmpdir, "", - Job{script_parameters: Tasks{[]TaskDef{ - TaskDef{commands: []string{"echo", "bar"}}, - TaskDef{commands: []string{"echo", "foo"}}}}}, - Task{sequence: 0}) + Job{Script_parameters: Tasks{[]TaskDef{{ + Command: []string{"echo", "foo"}, + KeepTmpOutput: true}}}}, + Task{Sequence: 0}) c.Check(err, IsNil) }