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