Merge branch '13245-cwl-dir-literal' closes #13245
[arvados.git] / services / keepstore / mounts_test.go
index bfe298b67bfdbf7a8adb83c9f4baaeea71508be5..0f7b6e97351a1a6049cb1ef49db69dcb1f29a6d7 100644 (file)
@@ -1,6 +1,11 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
 package main
 
 import (
+       "bytes"
        "context"
        "encoding/json"
        "net/http"
@@ -20,8 +25,10 @@ type MountsSuite struct {
 func (s *MountsSuite) SetUpTest(c *check.C) {
        s.vm = MakeTestVolumeManager(2)
        KeepVM = s.vm
-       s.rtr = MakeRESTRouter()
+       theConfig = DefaultConfig()
        theConfig.systemAuthToken = arvadostest.DataManagerToken
+       theConfig.Start()
+       s.rtr = MakeRESTRouter()
 }
 
 func (s *MountsSuite) TearDownTest(c *check.C) {
@@ -36,18 +43,31 @@ func (s *MountsSuite) TestMounts(c *check.C) {
        vols[0].Put(context.Background(), TestHash, TestBlock)
        vols[1].Put(context.Background(), TestHash2, TestBlock2)
 
-       resp := s.call("GET", "/mounts", "")
+       resp := s.call("GET", "/mounts", "", nil)
        c.Check(resp.Code, check.Equals, http.StatusOK)
        var mntList []struct {
-               UUID string
+               UUID           string   `json:"uuid"`
+               DeviceID       string   `json:"device_id"`
+               ReadOnly       bool     `json:"read_only"`
+               Replication    int      `json:"replication"`
+               StorageClasses []string `json:"storage_classes"`
        }
        err := json.Unmarshal(resp.Body.Bytes(), &mntList)
-       c.Check(err, check.IsNil)
-       c.Check(len(mntList), check.Equals, 2)
+       c.Assert(err, check.IsNil)
+       c.Assert(len(mntList), check.Equals, 2)
+       for _, m := range mntList {
+               c.Check(len(m.UUID), check.Equals, 27)
+               c.Check(m.UUID[:12], check.Equals, "zzzzz-ivpuk-")
+               c.Check(m.DeviceID, check.Equals, "mock-device-id")
+               c.Check(m.ReadOnly, check.Equals, false)
+               c.Check(m.Replication, check.Equals, 1)
+               c.Check(m.StorageClasses, check.DeepEquals, []string{"default"})
+       }
+       c.Check(mntList[0].UUID, check.Not(check.Equals), mntList[1].UUID)
 
        // Bad auth
        for _, tok := range []string{"", "xyzzy"} {
-               resp = s.call("GET", "/mounts/"+mntList[1].UUID+"/blocks", tok)
+               resp = s.call("GET", "/mounts/"+mntList[1].UUID+"/blocks", tok, nil)
                c.Check(resp.Code, check.Equals, http.StatusUnauthorized)
                c.Check(resp.Body.String(), check.Equals, "Unauthorized\n")
        }
@@ -55,34 +75,74 @@ func (s *MountsSuite) TestMounts(c *check.C) {
        tok := arvadostest.DataManagerToken
 
        // Nonexistent mount UUID
-       resp = s.call("GET", "/mounts/X/blocks", tok)
+       resp = s.call("GET", "/mounts/X/blocks", tok, nil)
        c.Check(resp.Code, check.Equals, http.StatusNotFound)
        c.Check(resp.Body.String(), check.Equals, "mount not found\n")
 
        // Complete index of first mount
-       resp = s.call("GET", "/mounts/"+mntList[0].UUID+"/blocks", tok)
+       resp = s.call("GET", "/mounts/"+mntList[0].UUID+"/blocks", tok, nil)
        c.Check(resp.Code, check.Equals, http.StatusOK)
        c.Check(resp.Body.String(), check.Matches, TestHash+`\+[0-9]+ [0-9]+\n\n`)
 
        // Partial index of first mount (one block matches prefix)
-       resp = s.call("GET", "/mounts/"+mntList[0].UUID+"/blocks/"+TestHash[:2], tok)
+       resp = s.call("GET", "/mounts/"+mntList[0].UUID+"/blocks?prefix="+TestHash[:2], tok, nil)
        c.Check(resp.Code, check.Equals, http.StatusOK)
        c.Check(resp.Body.String(), check.Matches, TestHash+`\+[0-9]+ [0-9]+\n\n`)
 
        // Complete index of second mount (note trailing slash)
-       resp = s.call("GET", "/mounts/"+mntList[1].UUID+"/blocks/", tok)
+       resp = s.call("GET", "/mounts/"+mntList[1].UUID+"/blocks/", tok, nil)
        c.Check(resp.Code, check.Equals, http.StatusOK)
        c.Check(resp.Body.String(), check.Matches, TestHash2+`\+[0-9]+ [0-9]+\n\n`)
 
        // Partial index of second mount (no blocks match prefix)
-       resp = s.call("GET", "/mounts/"+mntList[1].UUID+"/blocks/"+TestHash[:2], tok)
+       resp = s.call("GET", "/mounts/"+mntList[1].UUID+"/blocks/?prefix="+TestHash[:2], tok, nil)
        c.Check(resp.Code, check.Equals, http.StatusOK)
        c.Check(resp.Body.String(), check.Equals, "\n")
 }
 
-func (s *MountsSuite) call(method, path, tok string) *httptest.ResponseRecorder {
+func (s *MountsSuite) TestMetrics(c *check.C) {
+       s.call("PUT", "/"+TestHash, "", TestBlock)
+       s.call("PUT", "/"+TestHash2, "", TestBlock2)
+       resp := s.call("GET", "/metrics.json", "", nil)
+       c.Check(resp.Code, check.Equals, http.StatusOK)
+       var j []struct {
+               Name   string
+               Help   string
+               Type   string
+               Metric []struct {
+                       Label []struct {
+                               Name  string
+                               Value string
+                       }
+                       Summary struct {
+                               SampleCount string  `json:"sample_count"`
+                               SampleSum   float64 `json:"sample_sum"`
+                               Quantile    []struct {
+                                       Quantile float64
+                                       Value    float64
+                               }
+                       }
+               }
+       }
+       json.NewDecoder(resp.Body).Decode(&j)
+       found := make(map[string]bool)
+       for _, g := range j {
+               for _, m := range g.Metric {
+                       if len(m.Label) == 2 && m.Label[0].Name == "code" && m.Label[0].Value == "200" && m.Label[1].Name == "method" && m.Label[1].Value == "put" {
+                               c.Check(m.Summary.SampleCount, check.Equals, "2")
+                               c.Check(len(m.Summary.Quantile), check.Not(check.Equals), 0)
+                               c.Check(m.Summary.Quantile[0].Value, check.Not(check.Equals), float64(0))
+                               found[g.Name] = true
+                       }
+               }
+       }
+       c.Check(found["request_duration_seconds"], check.Equals, true)
+       c.Check(found["time_to_status_seconds"], check.Equals, true)
+}
+
+func (s *MountsSuite) call(method, path, tok string, body []byte) *httptest.ResponseRecorder {
        resp := httptest.NewRecorder()
-       req, _ := http.NewRequest(method, path, nil)
+       req, _ := http.NewRequest(method, path, bytes.NewReader(body))
        if tok != "" {
                req.Header.Set("Authorization", "OAuth2 "+tok)
        }