14 "git.curoverse.com/arvados.git/sdk/go/arvadosclient"
15 "git.curoverse.com/arvados.git/sdk/go/blockdigest"
16 "git.curoverse.com/arvados.git/sdk/go/keepclient"
21 // Gocheck boilerplate
22 func Test(t *testing.T) {
26 type KeepSuite struct{}
28 var _ = Suite(&KeepSuite{})
30 type TestHandler struct {
34 func (ts *TestHandler) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
35 r := json.NewDecoder(req.Body)
39 func (s *KeepSuite) TestSendTrashLists(c *C) {
41 server := httptest.NewServer(&th)
44 tl := map[string]TrashList{
45 server.URL: TrashList{TrashRequest{"000000000000000000000000deadbeef", 99}}}
47 arv := arvadosclient.ArvadosClient{ApiToken: "abc123"}
48 kc := keepclient.KeepClient{Arvados: &arv, Client: &http.Client{}}
49 kc.SetServiceRoots(map[string]string{"xxxx": server.URL},
50 map[string]string{"xxxx": server.URL},
53 err := SendTrashLists(&kc, tl)
63 type TestHandlerError struct {
66 func (tse *TestHandlerError) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
67 http.Error(writer, "I'm a teapot", 418)
70 func sendTrashListError(c *C, server *httptest.Server) {
71 tl := map[string]TrashList{
72 server.URL: TrashList{TrashRequest{"000000000000000000000000deadbeef", 99}}}
74 arv := arvadosclient.ArvadosClient{ApiToken: "abc123"}
75 kc := keepclient.KeepClient{Arvados: &arv, Client: &http.Client{}}
76 kc.SetServiceRoots(map[string]string{"xxxx": server.URL},
77 map[string]string{"xxxx": server.URL},
80 err := SendTrashLists(&kc, tl)
83 c.Check(err[0], NotNil)
86 func (s *KeepSuite) TestSendTrashListErrorResponse(c *C) {
87 server := httptest.NewServer(&TestHandlerError{})
88 sendTrashListError(c, server)
92 func (s *KeepSuite) TestSendTrashListUnreachable(c *C) {
93 sendTrashListError(c, httptest.NewUnstartedServer(&TestHandler{}))
96 type StatusAndBody struct {
101 type APIStub struct {
102 data map[string]StatusAndBody
105 func (stub *APIStub) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
106 if req.URL.Path == "/redirect-loop" {
107 http.Redirect(resp, req, "/redirect-loop", http.StatusFound)
111 pathResponse := stub.data[req.URL.Path]
112 if pathResponse.responseBody != "" {
113 if pathResponse.respStatus == -1 {
114 http.Redirect(resp, req, "/redirect-loop", http.StatusFound)
116 resp.WriteHeader(pathResponse.respStatus)
117 resp.Write([]byte(pathResponse.responseBody))
120 resp.WriteHeader(500)
121 resp.Write([]byte(``))
125 type KeepServerStub struct {
126 data map[string]StatusAndBody
129 func (stub *KeepServerStub) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
130 if req.URL.Path == "/redirect-loop" {
131 http.Redirect(resp, req, "/redirect-loop", http.StatusFound)
135 pathResponse := stub.data[req.URL.Path]
136 if pathResponse.responseBody != "" {
137 if pathResponse.respStatus == -1 {
138 http.Redirect(resp, req, "/redirect-loop", http.StatusFound)
140 resp.WriteHeader(pathResponse.respStatus)
141 resp.Write([]byte(pathResponse.responseBody))
144 resp.WriteHeader(500)
145 resp.Write([]byte(``))
149 type APITestData struct {
155 func (s *KeepSuite) TestGetKeepServers_UnsupportedServiceType(c *C) {
156 testGetKeepServersFromAPI(c, APITestData{1, "notadisk", 200}, "Unsupported service type")
159 func (s *KeepSuite) TestGetKeepServers_ReceivedTooFewServers(c *C) {
160 testGetKeepServersFromAPI(c, APITestData{2, "disk", 200}, "Did not receive all available keep servers")
163 func (s *KeepSuite) TestGetKeepServers_ServerError(c *C) {
164 testGetKeepServersFromAPI(c, APITestData{-1, "disk", -1}, "arvados API server error")
167 func testGetKeepServersFromAPI(c *C, testData APITestData, expectedError string) {
168 keepServers := ServiceList{
169 ItemsAvailable: testData.numServers,
170 KeepServers: []ServerAddress{{
175 ServiceType: testData.serverType,
179 ksJSON, _ := json.Marshal(keepServers)
180 apiData := make(map[string]StatusAndBody)
181 apiData["/arvados/v1/keep_services"] = StatusAndBody{testData.statusCode, string(ksJSON)}
182 apiStub := APIStub{apiData}
184 api := httptest.NewServer(&apiStub)
187 arv := arvadosclient.ArvadosClient{
189 ApiServer: api.URL[7:],
191 Client: &http.Client{Transport: &http.Transport{}},
194 kc := keepclient.KeepClient{Arvados: &arv, Client: &http.Client{}}
195 kc.SetServiceRoots(map[string]string{"xxxx": "http://example.com:23456"},
196 map[string]string{"xxxx": "http://example.com:23456"},
199 params := GetKeepServersParams{
205 _, err := GetKeepServersAndSummarize(params)
206 c.Assert(err, NotNil)
207 c.Assert(err, ErrorMatches, fmt.Sprintf(".*%s.*", expectedError))
210 type KeepServerTestData struct {
211 // handle /status.json
216 indexResponseBody string
218 // expected error, if any
222 func (s *KeepSuite) TestGetKeepServers_ErrorGettingKeepServerStatus(c *C) {
223 testGetKeepServersAndSummarize(c, KeepServerTestData{500, 200, "ok",
224 ".*http://.* 500 Internal Server Error"})
227 func (s *KeepSuite) TestGetKeepServers_GettingIndex(c *C) {
228 testGetKeepServersAndSummarize(c, KeepServerTestData{200, -1, "notok",
229 ".*redirect-loop.*"})
232 func (s *KeepSuite) TestGetKeepServers_ErrorReadServerResponse(c *C) {
233 testGetKeepServersAndSummarize(c, KeepServerTestData{200, 500, "notok",
234 ".*http://.* 500 Internal Server Error"})
237 func (s *KeepSuite) TestGetKeepServers_ReadServerResponseTuncatedAtLineOne(c *C) {
238 testGetKeepServersAndSummarize(c, KeepServerTestData{200, 200,
239 "notterminatedwithnewline", "Index from http://.* truncated at line 1"})
242 func (s *KeepSuite) TestGetKeepServers_InvalidBlockLocatorPattern(c *C) {
243 testGetKeepServersAndSummarize(c, KeepServerTestData{200, 200, "testing\n",
244 "Error parsing BlockInfo from index line.*"})
247 func (s *KeepSuite) TestGetKeepServers_ReadServerResponseEmpty(c *C) {
248 testGetKeepServersAndSummarize(c, KeepServerTestData{200, 200, "\n", ""})
251 func (s *KeepSuite) TestGetKeepServers_ReadServerResponseWithTwoBlocks(c *C) {
252 testGetKeepServersAndSummarize(c, KeepServerTestData{200, 200,
253 "51752ba076e461ec9ec1d27400a08548+20 1447526361\na048cc05c02ba1ee43ad071274b9e547+52 1447526362\n\n", ""})
256 func testGetKeepServersAndSummarize(c *C, testData KeepServerTestData) {
257 ksData := make(map[string]StatusAndBody)
258 ksData["/status.json"] = StatusAndBody{testData.statusStatusCode, string(`{}`)}
259 ksData["/index"] = StatusAndBody{testData.indexStatusCode, testData.indexResponseBody}
260 ksStub := KeepServerStub{ksData}
261 ks := httptest.NewServer(&ksStub)
264 ksURL, err := url.Parse(ks.URL)
266 ksHost, port, err := net.SplitHostPort(ksURL.Host)
267 ksPort, err := strconv.Atoi(port)
270 servers_list := ServiceList{
272 KeepServers: []ServerAddress{{
280 ksJSON, _ := json.Marshal(servers_list)
281 apiData := make(map[string]StatusAndBody)
282 apiData["/arvados/v1/keep_services"] = StatusAndBody{200, string(ksJSON)}
283 apiStub := APIStub{apiData}
285 api := httptest.NewServer(&apiStub)
288 arv := arvadosclient.ArvadosClient{
290 ApiServer: api.URL[7:],
292 Client: &http.Client{Transport: &http.Transport{}},
295 kc := keepclient.KeepClient{Arvados: &arv, Client: &http.Client{}}
296 kc.SetServiceRoots(map[string]string{"xxxx": ks.URL},
297 map[string]string{"xxxx": ks.URL},
300 params := GetKeepServersParams{
306 // GetKeepServersAndSummarize
307 results, err := GetKeepServersAndSummarize(params)
309 if testData.expectedError == "" {
311 c.Assert(results, NotNil)
313 blockToServers := results.BlockToServers
315 blockLocators := strings.Split(testData.indexResponseBody, "\n")
316 for _, loc := range blockLocators {
317 locator := strings.Split(loc, " ")[0]
319 blockLocator, err := blockdigest.ParseBlockLocator(locator)
322 blockDigestWithSize := blockdigest.DigestWithSize{blockLocator.Digest, uint32(blockLocator.Size)}
323 blockServerInfo := blockToServers[blockDigestWithSize]
324 c.Assert(blockServerInfo[0].Mtime, NotNil)
328 c.Assert(err, ErrorMatches, testData.expectedError)