Log if client hangs up while waiting for unix volume Serialize lock.
[arvados.git] / services / keepstore / volume_generic_test.go
index 23a17fd0998ebff4b8b3781dcf590534e88bc8a0..d5a413693f6c46c1d8241838a1ea87581191f9a4 100644 (file)
@@ -18,6 +18,8 @@ import (
 
        "git.curoverse.com/arvados.git/sdk/go/arvados"
        "git.curoverse.com/arvados.git/sdk/go/arvadostest"
+       "github.com/prometheus/client_golang/prometheus"
+       dto "github.com/prometheus/client_model/go"
 )
 
 type TB interface {
@@ -75,6 +77,8 @@ func DoGenericVolumeTests(t TB, factory TestableVolumeFactory) {
 
        testStatus(t, factory)
 
+       testMetrics(t, factory)
+
        testString(t, factory)
 
        testUpdateReadOnly(t, factory)
@@ -533,6 +537,84 @@ func testStatus(t TB, factory TestableVolumeFactory) {
        }
 }
 
+func getValueFrom(cv *prometheus.CounterVec, lbls prometheus.Labels) float64 {
+       c, _ := cv.GetMetricWith(lbls)
+       pb := &dto.Metric{}
+       c.Write(pb)
+       return pb.GetCounter().GetValue()
+}
+
+func testMetrics(t TB, factory TestableVolumeFactory) {
+       var err error
+
+       v := factory(t)
+       defer v.Teardown()
+       reg := prometheus.NewRegistry()
+       vm := newVolumeMetricsVecs(reg)
+
+       err = v.Start(vm)
+       if err != nil {
+               t.Error("Failed Start(): ", err)
+       }
+       opsC, _, ioC := vm.getCounterVecsFor(prometheus.Labels{"device_id": v.DeviceID()})
+
+       if ioC == nil {
+               t.Error("ioBytes CounterVec is nil")
+               return
+       }
+
+       if getValueFrom(ioC, prometheus.Labels{"direction": "out"})+
+               getValueFrom(ioC, prometheus.Labels{"direction": "in"}) > 0 {
+               t.Error("ioBytes counter should be zero")
+       }
+
+       if opsC == nil {
+               t.Error("opsCounter CounterVec is nil")
+               return
+       }
+
+       var c, writeOpCounter, readOpCounter float64
+
+       readOpType, writeOpType := v.ReadWriteOperationLabelValues()
+       writeOpCounter = getValueFrom(opsC, prometheus.Labels{"operation": writeOpType})
+       readOpCounter = getValueFrom(opsC, prometheus.Labels{"operation": readOpType})
+
+       // Test Put if volume is writable
+       if v.Writable() {
+               err = v.Put(context.Background(), TestHash, TestBlock)
+               if err != nil {
+                       t.Errorf("Got err putting block %q: %q, expected nil", TestBlock, err)
+               }
+               // Check that the write operations counter increased
+               c = getValueFrom(opsC, prometheus.Labels{"operation": writeOpType})
+               if c <= writeOpCounter {
+                       t.Error("Operation(s) not counted on Put")
+               }
+               // Check that bytes counter is > 0
+               if getValueFrom(ioC, prometheus.Labels{"direction": "out"}) == 0 {
+                       t.Error("ioBytes{direction=out} counter shouldn't be zero")
+               }
+       } else {
+               v.PutRaw(TestHash, TestBlock)
+       }
+
+       buf := make([]byte, BlockSize)
+       _, err = v.Get(context.Background(), TestHash, buf)
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       // Check that the operations counter increased
+       c = getValueFrom(opsC, prometheus.Labels{"operation": readOpType})
+       if c <= readOpCounter {
+               t.Error("Operation(s) not counted on Get")
+       }
+       // Check that the bytes "in" counter is > 0
+       if getValueFrom(ioC, prometheus.Labels{"direction": "in"}) == 0 {
+               t.Error("ioBytes{direction=in} counter shouldn't be zero")
+       }
+}
+
 // Invoke String for the volume; expect non-empty result
 // Test should pass for both writable and read-only volumes
 func testString(t TB, factory TestableVolumeFactory) {