1// Copyright 2018 The Prometheus Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14package blockdevice
15
16import (
17	"reflect"
18	"testing"
19)
20
21const (
22	failMsgFormat  = "%v, expected %v, actual %v"
23	procfsFixtures = "../fixtures/proc"
24	sysfsFixtures  = "../fixtures/sys"
25)
26
27func TestDiskstats(t *testing.T) {
28	blockdevice, err := NewFS(procfsFixtures, sysfsFixtures)
29	if err != nil {
30		t.Fatalf("failed to access blockdevice fs: %v", err)
31	}
32	diskstats, err := blockdevice.ProcDiskstats()
33	if err != nil {
34		t.Fatal(err)
35	}
36	expectedNumOfDevices := 52
37	if len(diskstats) != expectedNumOfDevices {
38		t.Errorf(failMsgFormat, "Incorrect number of devices", expectedNumOfDevices, len(diskstats))
39	}
40	if diskstats[0].DeviceName != "ram0" {
41		t.Errorf(failMsgFormat, "Incorrect device name", "ram0", diskstats[0].DeviceName)
42	}
43	if diskstats[1].IoStatsCount != 14 {
44		t.Errorf(failMsgFormat, "Incorrect number of stats read", 14, diskstats[0].IoStatsCount)
45	}
46	if diskstats[24].WriteIOs != 28444756 {
47		t.Errorf(failMsgFormat, "Incorrect writes completed", 28444756, diskstats[24].WriteIOs)
48	}
49	if diskstats[48].DiscardTicks != 11130 {
50		t.Errorf(failMsgFormat, "Incorrect discard time", 11130, diskstats[48].DiscardTicks)
51	}
52	if diskstats[48].IoStatsCount != 18 {
53		t.Errorf(failMsgFormat, "Incorrect number of stats read", 18, diskstats[48].IoStatsCount)
54	}
55	if diskstats[49].IoStatsCount != 20 {
56		t.Errorf(failMsgFormat, "Incorrect number of stats read", 20, diskstats[50].IoStatsCount)
57	}
58	if diskstats[49].FlushRequestsCompleted != 127 {
59		t.Errorf(failMsgFormat, "Incorrect number of flash requests completed", 127, diskstats[50].FlushRequestsCompleted)
60	}
61	if diskstats[49].TimeSpentFlushing != 182 {
62		t.Errorf(failMsgFormat, "Incorrect time spend flushing", 182, diskstats[50].TimeSpentFlushing)
63	}
64}
65
66func TestBlockDevice(t *testing.T) {
67	blockdevice, err := NewFS("../fixtures/proc", "../fixtures/sys")
68	if err != nil {
69		t.Fatalf("failed to access blockdevice fs: %v", err)
70	}
71	devices, err := blockdevice.SysBlockDevices()
72	if err != nil {
73		t.Fatal(err)
74	}
75	expectedNumOfDevices := 2
76	if len(devices) != expectedNumOfDevices {
77		t.Fatalf(failMsgFormat, "Incorrect number of devices", expectedNumOfDevices, len(devices))
78	}
79	if devices[0] != "dm-0" {
80		t.Errorf(failMsgFormat, "Incorrect device name", "dm-0", devices[0])
81	}
82	device0stats, count, err := blockdevice.SysBlockDeviceStat(devices[0])
83	if err != nil {
84		t.Fatal(err)
85	}
86	if count != 11 {
87		t.Errorf(failMsgFormat, "Incorrect number of stats read", 11, count)
88	}
89	if device0stats.ReadIOs != 6447303 {
90		t.Errorf(failMsgFormat, "Incorrect read I/Os", 6447303, device0stats.ReadIOs)
91	}
92	if device0stats.WeightedIOTicks != 6088971 {
93		t.Errorf(failMsgFormat, "Incorrect time in queue", 6088971, device0stats.WeightedIOTicks)
94	}
95	device1stats, count, err := blockdevice.SysBlockDeviceStat(devices[1])
96	if count != 15 {
97		t.Errorf(failMsgFormat, "Incorrect number of stats read", 15, count)
98	}
99	if err != nil {
100		t.Fatal(err)
101	}
102	if device1stats.WriteSectors != 286915323 {
103		t.Errorf(failMsgFormat, "Incorrect write merges", 286915323, device1stats.WriteSectors)
104	}
105	if device1stats.DiscardTicks != 12 {
106		t.Errorf(failMsgFormat, "Incorrect discard ticks", 12, device1stats.DiscardTicks)
107	}
108	blockQueueStatExpected := BlockQueueStats{
109		AddRandom:            1,
110		DAX:                  0,
111		DiscardGranularity:   0,
112		DiscardMaxHWBytes:    0,
113		DiscardMaxBytes:      0,
114		HWSectorSize:         512,
115		IOPoll:               0,
116		IOPollDelay:          -1,
117		IOTimeout:            30000,
118		IOStats:              1,
119		LogicalBlockSize:     512,
120		MaxHWSectorsKB:       32767,
121		MaxIntegritySegments: 0,
122		MaxSectorsKB:         1280,
123		MaxSegments:          168,
124		MaxSegmentSize:       65536,
125		MinimumIOSize:        512,
126		NoMerges:             0,
127		NRRequests:           64,
128		OptimalIOSize:        0,
129		PhysicalBlockSize:    512,
130		ReadAHeadKB:          128,
131		Rotational:           1,
132		RQAffinity:           1,
133		SchedulerList:        []string{"mq-deadline", "kyber", "bfq", "none"},
134		SchedulerCurrent:     "bfq",
135		WriteCache:           "write back",
136		WriteSameMaxBytes:    0,
137		WBTLatUSec:           75000,
138		ThrottleSampleTime:   nil,
139		Zoned:                "none",
140		NRZones:              0,
141		ChunkSectors:         0,
142		FUA:                  0,
143		MaxDiscardSegments:   1,
144		WriteZeroesMaxBytes:  0,
145	}
146
147	blockQueueStat, err := blockdevice.SysBlockDeviceQueueStats(devices[1])
148	if err != nil {
149		t.Fatal(err)
150	}
151	if !reflect.DeepEqual(blockQueueStat, blockQueueStatExpected) {
152		t.Errorf("Incorrect BlockQueueStat, expected: \n%+v, got: \n%+v", blockQueueStatExpected, blockQueueStat)
153	}
154}
155