1// Copyright 2017 The etcd Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package integration
16
17import (
18	"context"
19	"strconv"
20	"testing"
21	"time"
22
23	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
24	"github.com/coreos/etcd/pkg/testutil"
25)
26
27// TestMetricDbSizeBoot checks that the db size metric is set on boot.
28func TestMetricDbSizeBoot(t *testing.T) {
29	defer testutil.AfterTest(t)
30	clus := NewClusterV3(t, &ClusterConfig{Size: 1})
31	defer clus.Terminate(t)
32
33	v, err := clus.Members[0].Metric("etcd_debugging_mvcc_db_total_size_in_bytes")
34	if err != nil {
35		t.Fatal(err)
36	}
37
38	if v == "0" {
39		t.Fatalf("expected non-zero, got %q", v)
40	}
41}
42
43// TestMetricDbSizeDefrag checks that the db size metric is set after defrag.
44func TestMetricDbSizeDefrag(t *testing.T) {
45	defer testutil.AfterTest(t)
46	clus := NewClusterV3(t, &ClusterConfig{Size: 1})
47	defer clus.Terminate(t)
48
49	kvc := toGRPC(clus.Client(0)).KV
50	mc := toGRPC(clus.Client(0)).Maintenance
51
52	// expand the db size
53	numPuts := 25 // large enough to write more than 1 page
54	putreq := &pb.PutRequest{Key: []byte("k"), Value: make([]byte, 4096)}
55	for i := 0; i < numPuts; i++ {
56		if _, err := kvc.Put(context.TODO(), putreq); err != nil {
57			t.Fatal(err)
58		}
59	}
60
61	// wait for backend txn sync
62	time.Sleep(500 * time.Millisecond)
63
64	beforeDefrag, err := clus.Members[0].Metric("etcd_debugging_mvcc_db_total_size_in_bytes")
65	if err != nil {
66		t.Fatal(err)
67	}
68	bv, err := strconv.Atoi(beforeDefrag)
69	if err != nil {
70		t.Fatal(err)
71	}
72	if expected := numPuts * len(putreq.Value); bv < expected {
73		t.Fatalf("expected db size greater than %d, got %d", expected, bv)
74	}
75
76	// clear out historical keys
77	creq := &pb.CompactionRequest{Revision: int64(numPuts), Physical: true}
78	if _, err := kvc.Compact(context.TODO(), creq); err != nil {
79		t.Fatal(err)
80	}
81
82	// defrag should give freed space back to fs
83	mc.Defragment(context.TODO(), &pb.DefragmentRequest{})
84	afterDefrag, err := clus.Members[0].Metric("etcd_debugging_mvcc_db_total_size_in_bytes")
85	if err != nil {
86		t.Fatal(err)
87	}
88
89	av, err := strconv.Atoi(afterDefrag)
90	if err != nil {
91		t.Fatal(err)
92	}
93
94	if bv <= av {
95		t.Fatalf("expected less than %d, got %d after defrag", bv, av)
96	}
97}
98