"io/ioutil"
"os"
"os/exec"
+ "path/filepath"
"sort"
"strings"
"sync"
stop chan bool
cwd string
env []string
+ api *ArvTestClient
}
func NewTestDockerClient() *TestDockerClient {
return nil
}
+var discoveryMap = map[string]interface{}{"defaultTrashLifetime": float64(1209600)}
+
+func (client *ArvTestClient) Discovery(key string) (interface{}, error) {
+ return discoveryMap[key], nil
+}
+
// CalledWith returns the parameters from the first API call whose
// parameters match jpath/string. E.g., CalledWith(c, "foo.bar",
// "baz") returns parameters with parameters["foo"]["bar"]=="baz". If
return nil
}
+func (ArvErrorTestClient) Discovery(key string) (interface{}, error) {
+ return discoveryMap[key], nil
+}
+
type KeepErrorTestClient struct{}
func (KeepErrorTestClient) PutHB(hash string, buf []byte) (string, int, error) {
docker.RemoveImage(hwImageId, true)
api = &ArvTestClient{Container: rec}
+ docker.api = api
cr = NewContainerRunner(api, &KeepTestClient{}, docker, "zzzzz-zzzzz-zzzzzzzzzzzzzzz")
cr.statInterval = 100 * time.Millisecond
am := &ArvMountCmdLine{}
am := &ArvMountCmdLine{}
cr.RunArvMount = am.ArvMountTest
+ realTemp, err := ioutil.TempDir("", "crunchrun_test-")
+ c.Assert(err, IsNil)
+ defer os.RemoveAll(realTemp)
+
i := 0
- cr.MkTempDir = func(string, string) (string, error) {
- i += 1
- d := fmt.Sprintf("/tmp/mktmpdir%d", i)
- os.Mkdir(d, os.ModePerm)
- return d, nil
+ cr.MkTempDir = func(_ string, prefix string) (string, error) {
+ i++
+ d := fmt.Sprintf("%s/%s%d", realTemp, prefix, i)
+ err := os.Mkdir(d, os.ModePerm)
+ if err != nil && strings.Contains(err.Error(), ": file exists") {
+ // Test case must have pre-populated the tempdir
+ err = nil
+ }
+ return d, err
+ }
+
+ checkEmpty := func() {
+ filepath.Walk(realTemp, func(path string, _ os.FileInfo, err error) error {
+ c.Check(path, Equals, realTemp)
+ c.Check(err, IsNil)
+ return nil
+ })
}
{
+ i = 0
cr.Container.Mounts = make(map[string]arvados.Mount)
cr.Container.Mounts["/tmp"] = arvados.Mount{Kind: "tmp"}
cr.OutputPath = "/tmp"
err := cr.SetupMounts()
c.Check(err, IsNil)
- c.Check(am.Cmd, DeepEquals, []string{"--foreground", "--allow-other", "--read-write", "--mount-by-pdh", "by_id", "/tmp/mktmpdir1"})
- c.Check(cr.Binds, DeepEquals, []string{"/tmp/mktmpdir2:/tmp"})
+ c.Check(am.Cmd, DeepEquals, []string{"--foreground", "--allow-other", "--read-write", "--mount-by-pdh", "by_id", realTemp + "/keep1"})
+ c.Check(cr.Binds, DeepEquals, []string{realTemp + "/2:/tmp"})
cr.CleanupDirs()
+ checkEmpty()
}
{
i = 0
- cr.Container.Mounts = make(map[string]arvados.Mount)
- cr.Container.Mounts["/keeptmp"] = arvados.Mount{Kind: "collection", Writable: true}
+ cr.Container.Mounts = map[string]arvados.Mount{
+ "/keeptmp": {Kind: "collection", Writable: true},
+ }
cr.OutputPath = "/keeptmp"
- os.MkdirAll("/tmp/mktmpdir1/tmp0", os.ModePerm)
+ os.MkdirAll(realTemp+"/keep1/tmp0", os.ModePerm)
err := cr.SetupMounts()
c.Check(err, IsNil)
- c.Check(am.Cmd, DeepEquals, []string{"--foreground", "--allow-other", "--read-write", "--mount-tmp", "tmp0", "--mount-by-pdh", "by_id", "/tmp/mktmpdir1"})
- c.Check(cr.Binds, DeepEquals, []string{"/tmp/mktmpdir1/tmp0:/keeptmp"})
+ c.Check(am.Cmd, DeepEquals, []string{"--foreground", "--allow-other", "--read-write", "--mount-tmp", "tmp0", "--mount-by-pdh", "by_id", realTemp + "/keep1"})
+ c.Check(cr.Binds, DeepEquals, []string{realTemp + "/keep1/tmp0:/keeptmp"})
cr.CleanupDirs()
+ checkEmpty()
}
{
i = 0
- cr.Container.Mounts = make(map[string]arvados.Mount)
- cr.Container.Mounts["/keepinp"] = arvados.Mount{Kind: "collection", PortableDataHash: "59389a8f9ee9d399be35462a0f92541c+53"}
- cr.Container.Mounts["/keepout"] = arvados.Mount{Kind: "collection", Writable: true}
+ cr.Container.Mounts = map[string]arvados.Mount{
+ "/keepinp": {Kind: "collection", PortableDataHash: "59389a8f9ee9d399be35462a0f92541c+53"},
+ "/keepout": {Kind: "collection", Writable: true},
+ }
cr.OutputPath = "/keepout"
- os.MkdirAll("/tmp/mktmpdir1/by_id/59389a8f9ee9d399be35462a0f92541c+53", os.ModePerm)
- os.MkdirAll("/tmp/mktmpdir1/tmp0", os.ModePerm)
+ os.MkdirAll(realTemp+"/keep1/by_id/59389a8f9ee9d399be35462a0f92541c+53", os.ModePerm)
+ os.MkdirAll(realTemp+"/keep1/tmp0", os.ModePerm)
err := cr.SetupMounts()
c.Check(err, IsNil)
- c.Check(am.Cmd, DeepEquals, []string{"--foreground", "--allow-other", "--read-write", "--mount-tmp", "tmp0", "--mount-by-pdh", "by_id", "/tmp/mktmpdir1"})
- var ss sort.StringSlice = cr.Binds
- ss.Sort()
- c.Check(cr.Binds, DeepEquals, []string{"/tmp/mktmpdir1/by_id/59389a8f9ee9d399be35462a0f92541c+53:/keepinp:ro",
- "/tmp/mktmpdir1/tmp0:/keepout"})
+ c.Check(am.Cmd, DeepEquals, []string{"--foreground", "--allow-other", "--read-write", "--mount-tmp", "tmp0", "--mount-by-pdh", "by_id", realTemp + "/keep1"})
+ sort.StringSlice(cr.Binds).Sort()
+ c.Check(cr.Binds, DeepEquals, []string{realTemp + "/keep1/by_id/59389a8f9ee9d399be35462a0f92541c+53:/keepinp:ro",
+ realTemp + "/keep1/tmp0:/keepout"})
+ cr.CleanupDirs()
+ checkEmpty()
+ }
+
+ {
+ i = 0
+ cr.Container.RuntimeConstraints.KeepCacheRAM = 512
+ cr.Container.Mounts = map[string]arvados.Mount{
+ "/keepinp": {Kind: "collection", PortableDataHash: "59389a8f9ee9d399be35462a0f92541c+53"},
+ "/keepout": {Kind: "collection", Writable: true},
+ }
+ cr.OutputPath = "/keepout"
+
+ os.MkdirAll(realTemp+"/keep1/by_id/59389a8f9ee9d399be35462a0f92541c+53", os.ModePerm)
+ os.MkdirAll(realTemp+"/keep1/tmp0", os.ModePerm)
+
+ err := cr.SetupMounts()
+ c.Check(err, IsNil)
+ c.Check(am.Cmd, DeepEquals, []string{"--foreground", "--allow-other", "--read-write", "--file-cache", "512", "--mount-tmp", "tmp0", "--mount-by-pdh", "by_id", realTemp + "/keep1"})
+ sort.StringSlice(cr.Binds).Sort()
+ c.Check(cr.Binds, DeepEquals, []string{realTemp + "/keep1/by_id/59389a8f9ee9d399be35462a0f92541c+53:/keepinp:ro",
+ realTemp + "/keep1/tmp0:/keepout"})
+ cr.CleanupDirs()
+ checkEmpty()
+ }
+
+ for _, test := range []struct {
+ in interface{}
+ out string
+ }{
+ {in: "foo", out: `"foo"`},
+ {in: nil, out: `null`},
+ {in: map[string]int{"foo": 123}, out: `{"foo":123}`},
+ } {
+ i = 0
+ cr.Container.Mounts = map[string]arvados.Mount{
+ "/mnt/test.json": {Kind: "json", Content: test.in},
+ }
+ err := cr.SetupMounts()
+ c.Check(err, IsNil)
+ sort.StringSlice(cr.Binds).Sort()
+ c.Check(cr.Binds, DeepEquals, []string{realTemp + "/2/mountdata.json:/mnt/test.json:ro"})
+ content, err := ioutil.ReadFile(realTemp + "/2/mountdata.json")
+ c.Check(err, IsNil)
+ c.Check(content, DeepEquals, []byte(test.out))
cr.CleanupDirs()
+ checkEmpty()
}
}
c.Check(err, NotNil)
c.Check(strings.Contains(err.Error(), "Unsupported mount kind 'collection' for stdout"), Equals, true)
}
+
+func (s *TestSuite) TestFullRunWithAPI(c *C) {
+ os.Setenv("ARVADOS_API_HOST", "test.arvados.org")
+ defer os.Unsetenv("ARVADOS_API_HOST")
+ api, _ := FullRunHelper(c, `{
+ "command": ["/bin/sh", "-c", "echo $ARVADOS_API_HOST"],
+ "container_image": "d4ab34d3d4f8a72f5c4973051ae69fab+122",
+ "cwd": "/bin",
+ "environment": {},
+ "mounts": {"/tmp": {"kind": "tmp"} },
+ "output_path": "/tmp",
+ "priority": 1,
+ "runtime_constraints": {"API": true}
+}`, func(t *TestDockerClient) {
+ t.logWriter.Write(dockerLog(1, t.env[1][17:]+"\n"))
+ t.logWriter.Close()
+ t.finish <- dockerclient.WaitResult{ExitCode: 0}
+ })
+
+ c.Check(api.CalledWith("container.exit_code", 0), NotNil)
+ c.Check(api.CalledWith("container.state", "Complete"), NotNil)
+ c.Check(strings.HasSuffix(api.Logs["stdout"].String(), "test.arvados.org\n"), Equals, true)
+ c.Check(api.CalledWith("container.output", "d41d8cd98f00b204e9800998ecf8427e+0"), NotNil)
+}
+
+func (s *TestSuite) TestFullRunSetOutput(c *C) {
+ os.Setenv("ARVADOS_API_HOST", "test.arvados.org")
+ defer os.Unsetenv("ARVADOS_API_HOST")
+ api, _ := FullRunHelper(c, `{
+ "command": ["/bin/sh", "-c", "echo $ARVADOS_API_HOST"],
+ "container_image": "d4ab34d3d4f8a72f5c4973051ae69fab+122",
+ "cwd": "/bin",
+ "environment": {},
+ "mounts": {"/tmp": {"kind": "tmp"} },
+ "output_path": "/tmp",
+ "priority": 1,
+ "runtime_constraints": {"API": true}
+}`, func(t *TestDockerClient) {
+ t.api.Container.Output = "d4ab34d3d4f8a72f5c4973051ae69fab+122"
+ t.logWriter.Close()
+ t.finish <- dockerclient.WaitResult{ExitCode: 0}
+ })
+
+ c.Check(api.CalledWith("container.exit_code", 0), NotNil)
+ c.Check(api.CalledWith("container.state", "Complete"), NotNil)
+ c.Check(api.CalledWith("container.output", "d4ab34d3d4f8a72f5c4973051ae69fab+122"), NotNil)
+}