Add 'tools/arvbox/' from commit 'd3d368758db1f4a9fa5b89f77b5ee61d68ef5b72'
[arvados.git] / services / crunch-dispatch-local / crunch-dispatch-local_test.go
1 package main
2
3 import (
4         "git.curoverse.com/arvados.git/sdk/go/arvadosclient"
5         "git.curoverse.com/arvados.git/sdk/go/arvadostest"
6
7         "io/ioutil"
8         "log"
9         "net/http"
10         "net/http/httptest"
11         "os"
12         "strings"
13         "syscall"
14         "testing"
15         "time"
16
17         . "gopkg.in/check.v1"
18 )
19
20 // Gocheck boilerplate
21 func Test(t *testing.T) {
22         TestingT(t)
23 }
24
25 var _ = Suite(&TestSuite{})
26 var _ = Suite(&MockArvadosServerSuite{})
27
28 type TestSuite struct{}
29 type MockArvadosServerSuite struct{}
30
31 var initialArgs []string
32
33 func (s *TestSuite) SetUpSuite(c *C) {
34         initialArgs = os.Args
35         arvadostest.StartAPI()
36 }
37
38 func (s *TestSuite) TearDownSuite(c *C) {
39         arvadostest.StopAPI()
40 }
41
42 func (s *TestSuite) SetUpTest(c *C) {
43         args := []string{"crunch-dispatch-local"}
44         os.Args = args
45
46         var err error
47         arv, err = arvadosclient.MakeArvadosClient()
48         if err != nil {
49                 c.Fatalf("Error making arvados client: %s", err)
50         }
51 }
52
53 func (s *TestSuite) TearDownTest(c *C) {
54         arvadostest.ResetEnv()
55         os.Args = initialArgs
56 }
57
58 func (s *MockArvadosServerSuite) TearDownTest(c *C) {
59         arvadostest.ResetEnv()
60 }
61
62 func (s *TestSuite) Test_doMain(c *C) {
63         args := []string{"-poll-interval", "2", "-container-priority-poll-interval", "1", "-crunch-run-command", "echo"}
64         os.Args = append(os.Args, args...)
65
66         go func() {
67                 time.Sleep(5 * time.Second)
68                 sigChan <- syscall.SIGINT
69         }()
70
71         err := doMain()
72         c.Check(err, IsNil)
73
74         // There should be no queued containers now
75         params := arvadosclient.Dict{
76                 "filters": [][]string{[]string{"state", "=", "Queued"}},
77         }
78         var containers ContainerList
79         err = arv.List("containers", params, &containers)
80         c.Check(err, IsNil)
81         c.Assert(len(containers.Items), Equals, 0)
82
83         // Previously "Queued" container should now be in "Complete" state
84         var container Container
85         err = arv.Get("containers", "zzzzz-dz642-queuedcontainer", nil, &container)
86         c.Check(err, IsNil)
87         c.Check(container.State, Equals, "Complete")
88 }
89
90 func (s *MockArvadosServerSuite) Test_APIErrorGettingContainers(c *C) {
91         apiStubResponses := make(map[string]arvadostest.StubResponse)
92         apiStubResponses["/arvados/v1/containers"] = arvadostest.StubResponse{500, string(`{}`)}
93
94         testWithServerStub(c, apiStubResponses, "echo", "Error getting list of queued containers")
95 }
96
97 func (s *MockArvadosServerSuite) Test_APIErrorUpdatingContainerState(c *C) {
98         apiStubResponses := make(map[string]arvadostest.StubResponse)
99         apiStubResponses["/arvados/v1/containers"] =
100                 arvadostest.StubResponse{200, string(`{"items_available":1, "items":[{"uuid":"zzzzz-dz642-xxxxxxxxxxxxxx1"}]}`)}
101         apiStubResponses["/arvados/v1/containers/zzzzz-dz642-xxxxxxxxxxxxxx1"] =
102                 arvadostest.StubResponse{500, string(`{}`)}
103
104         testWithServerStub(c, apiStubResponses, "echo", "Error updating container state")
105 }
106
107 func (s *MockArvadosServerSuite) Test_ContainerStillInRunningAfterRun(c *C) {
108         apiStubResponses := make(map[string]arvadostest.StubResponse)
109         apiStubResponses["/arvados/v1/containers"] =
110                 arvadostest.StubResponse{200, string(`{"items_available":1, "items":[{"uuid":"zzzzz-dz642-xxxxxxxxxxxxxx2"}]}`)}
111         apiStubResponses["/arvados/v1/containers/zzzzz-dz642-xxxxxxxxxxxxxx2"] =
112                 arvadostest.StubResponse{200, string(`{"uuid":"zzzzz-dz642-xxxxxxxxxxxxxx2", "state":"Running", "priority":1}`)}
113
114         testWithServerStub(c, apiStubResponses, "echo",
115                 "After crunch-run process termination, the state is still 'Running' for zzzzz-dz642-xxxxxxxxxxxxxx2")
116 }
117
118 func (s *MockArvadosServerSuite) Test_ErrorRunningContainer(c *C) {
119         apiStubResponses := make(map[string]arvadostest.StubResponse)
120         apiStubResponses["/arvados/v1/containers"] =
121                 arvadostest.StubResponse{200, string(`{"items_available":1, "items":[{"uuid":"zzzzz-dz642-xxxxxxxxxxxxxx3"}]}`)}
122         apiStubResponses["/arvados/v1/containers/zzzzz-dz642-xxxxxxxxxxxxxx3"] =
123                 arvadostest.StubResponse{200, string(`{"uuid":"zzzzz-dz642-xxxxxxxxxxxxxx3", "state":"Running", "priority":1}`)}
124
125         testWithServerStub(c, apiStubResponses, "nosuchcommand", "Error running container for zzzzz-dz642-xxxxxxxxxxxxxx3")
126 }
127
128 func testWithServerStub(c *C, apiStubResponses map[string]arvadostest.StubResponse, crunchCmd string, expected string) {
129         apiStub := arvadostest.ServerStub{apiStubResponses}
130
131         api := httptest.NewServer(&apiStub)
132         defer api.Close()
133
134         arv = arvadosclient.ArvadosClient{
135                 Scheme:    "http",
136                 ApiServer: api.URL[7:],
137                 ApiToken:  "abc123",
138                 Client:    &http.Client{Transport: &http.Transport{}},
139                 Retries:   0,
140         }
141
142         tempfile, err := ioutil.TempFile(os.TempDir(), "temp-log-file")
143         c.Check(err, IsNil)
144         defer os.Remove(tempfile.Name())
145         log.SetOutput(tempfile)
146
147         go func() {
148                 time.Sleep(2 * time.Second)
149                 sigChan <- syscall.SIGTERM
150         }()
151
152         runQueuedContainers(1, 1, crunchCmd)
153
154         // Wait for all running crunch jobs to complete / terminate
155         waitGroup.Wait()
156
157         buf, _ := ioutil.ReadFile(tempfile.Name())
158         c.Check(strings.Contains(string(buf), expected), Equals, true)
159 }