master
go 246 lines 6.67 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 //go:build linux
4
5 package dmcache
6
7 import (
8 "context"
9 "errors"
10 "os"
11 "testing"
12
13 "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/collecttest"
14
15 "github.com/stretchr/testify/assert"
16 "github.com/stretchr/testify/require"
17 )
18
19 var (
20 dataConfigJSON, _ = os.ReadFile("testdata/config.json")
21 dataConfigYAML, _ = os.ReadFile("testdata/config.yaml")
22 )
23
24 func Test_testDataIsValid(t *testing.T) {
25 for name, data := range map[string][]byte{
26 "dataConfigJSON": dataConfigJSON,
27 "dataConfigYAML": dataConfigYAML,
28 } {
29 require.NotNil(t, data, name)
30
31 }
32 }
33
34 func TestCollector_Configuration(t *testing.T) {
35 collecttest.TestConfigurationSerialize(t, &Collector{}, dataConfigJSON, dataConfigYAML)
36 }
37
38 func TestCollector_Init(t *testing.T) {
39 tests := map[string]struct {
40 config Config
41 wantFail bool
42 }{
43 "success with default config": {
44 wantFail: false,
45 config: New().Config,
46 },
47 }
48
49 for name, test := range tests {
50 t.Run(name, func(t *testing.T) {
51 collr := New()
52 collr.Config = test.config
53
54 if test.wantFail {
55 assert.Error(t, collr.Init(context.Background()))
56 } else {
57 assert.NoError(t, collr.Init(context.Background()))
58 }
59 })
60 }
61 }
62
63 func TestCollector_Cleanup(t *testing.T) {
64 tests := map[string]struct {
65 prepare func() *Collector
66 }{
67 "not initialized exec": {
68 prepare: func() *Collector {
69 return New()
70 },
71 },
72 "after check": {
73 prepare: func() *Collector {
74 collr := New()
75 collr.exec = prepareMockOK()
76 _ = collr.Check(context.Background())
77 return collr
78 },
79 },
80 "after collect": {
81 prepare: func() *Collector {
82 collr := New()
83 collr.exec = prepareMockOK()
84 _ = collr.Collect(context.Background())
85 return collr
86 },
87 },
88 }
89
90 for name, test := range tests {
91 t.Run(name, func(t *testing.T) {
92 collr := test.prepare()
93
94 assert.NotPanics(t, func() { collr.Cleanup(context.Background()) })
95 })
96 }
97 }
98
99 func TestCollector_Charts(t *testing.T) {
100 assert.NotNil(t, New().Charts())
101 }
102
103 func TestCollector_Check(t *testing.T) {
104 tests := map[string]struct {
105 prepareMock func() *mockDmsetupExec
106 wantFail bool
107 }{
108 "success case": {
109 prepareMock: prepareMockOK,
110 wantFail: false,
111 },
112 "error on cache status": {
113 prepareMock: prepareMockErr,
114 wantFail: true,
115 },
116 "empty response": {
117 prepareMock: prepareMockEmptyResponse,
118 wantFail: true,
119 },
120 "unexpected response": {
121 prepareMock: prepareMockUnexpectedResponse,
122 wantFail: true,
123 },
124 }
125
126 for name, test := range tests {
127 t.Run(name, func(t *testing.T) {
128 collr := New()
129 mock := test.prepareMock()
130 collr.exec = mock
131
132 if test.wantFail {
133 assert.Error(t, collr.Check(context.Background()))
134 } else {
135 assert.NoError(t, collr.Check(context.Background()))
136 }
137 })
138 }
139 }
140
141 func TestLVM_Collect(t *testing.T) {
142 tests := map[string]struct {
143 prepareMock func() *mockDmsetupExec
144 wantCharts int
145 wantMetrics map[string]int64
146 }{
147 "success case": {
148 prepareMock: prepareMockOK,
149 wantCharts: len(deviceChartsTmpl) * 2,
150 wantMetrics: map[string]int64{
151 "dmcache_device_vg_raid1_md21-media_cache_free_bytes": 1252402397184,
152 "dmcache_device_vg_raid1_md21-media_cache_used_bytes": 396412059648,
153 "dmcache_device_vg_raid1_md21-media_demotions_bytes": 0,
154 "dmcache_device_vg_raid1_md21-media_dirty_bytes": 0,
155 "dmcache_device_vg_raid1_md21-media_metadata_free_bytes": 32243712,
156 "dmcache_device_vg_raid1_md21-media_metadata_used_bytes": 9699328,
157 "dmcache_device_vg_raid1_md21-media_promotions_bytes": 48035266560,
158 "dmcache_device_vg_raid1_md21-media_read_hits": 82870357,
159 "dmcache_device_vg_raid1_md21-media_read_misses": 5499462,
160 "dmcache_device_vg_raid1_md21-media_write_hits": 26280342,
161 "dmcache_device_vg_raid1_md21-media_write_misses": 8017854,
162 "dmcache_device_vg_raid2_md22-media_cache_free_bytes": 1252402397184,
163 "dmcache_device_vg_raid2_md22-media_cache_used_bytes": 396412059648,
164 "dmcache_device_vg_raid2_md22-media_demotions_bytes": 0,
165 "dmcache_device_vg_raid2_md22-media_dirty_bytes": 0,
166 "dmcache_device_vg_raid2_md22-media_metadata_free_bytes": 32243712,
167 "dmcache_device_vg_raid2_md22-media_metadata_used_bytes": 9699328,
168 "dmcache_device_vg_raid2_md22-media_promotions_bytes": 48035266560,
169 "dmcache_device_vg_raid2_md22-media_read_hits": 82870357,
170 "dmcache_device_vg_raid2_md22-media_read_misses": 5499462,
171 "dmcache_device_vg_raid2_md22-media_write_hits": 26280342,
172 "dmcache_device_vg_raid2_md22-media_write_misses": 8017854,
173 },
174 },
175 "error on cache status": {
176 prepareMock: prepareMockErr,
177 wantMetrics: nil,
178 },
179 "empty response": {
180 prepareMock: prepareMockEmptyResponse,
181 wantMetrics: nil,
182 },
183 "unexpected response": {
184 prepareMock: prepareMockUnexpectedResponse,
185 wantMetrics: nil,
186 },
187 }
188
189 for name, test := range tests {
190 t.Run(name, func(t *testing.T) {
191 collr := New()
192 mock := test.prepareMock()
193 collr.exec = mock
194
195 mx := collr.Collect(context.Background())
196
197 assert.Equal(t, test.wantMetrics, mx)
198
199 assert.Len(t, *collr.Charts(), test.wantCharts, "wantCharts")
200
201 collecttest.TestMetricsHasAllChartsDims(t, collr.Charts(), mx)
202 })
203 }
204 }
205
206 func prepareMockOK() *mockDmsetupExec {
207 return &mockDmsetupExec{
208 cacheStatusData: []byte(`
209 vg_raid1_md21-media: 0 2404139008 cache 8 2368/10240 4096 189024/786216 82870357 5499462 26280342 8017854 0 22905 0 3 metadata2 writethrough no_discard_passdown 2 migration_threshold 32768 mq 10 random_threshold 0 sequential_threshold 0 discard_promote_adjustment 0 read_promote_adjustment 0 write_promote_adjustment 0 rw -
210 vg_raid2_md22-media: 0 2404139008 cache 8 2368/10240 4096 189024/786216 82870357 5499462 26280342 8017854 0 22905 0 3 metadata2 writethrough no_discard_passdown 2 migration_threshold 32768 mq 10 random_threshold 0 sequential_threshold 0 discard_promote_adjustment 0 read_promote_adjustment 0 write_promote_adjustment 0 rw -
211 `),
212 }
213 }
214
215 func prepareMockErr() *mockDmsetupExec {
216 return &mockDmsetupExec{
217 errOnCacheStatus: true,
218 }
219 }
220
221 func prepareMockEmptyResponse() *mockDmsetupExec {
222 return &mockDmsetupExec{}
223 }
224
225 func prepareMockUnexpectedResponse() *mockDmsetupExec {
226 return &mockDmsetupExec{
227 cacheStatusData: []byte(`
228 Lorem ipsum dolor sit amet, consectetur adipiscing elit.
229 Nulla malesuada erat id magna mattis, eu viverra tellus rhoncus.
230 Fusce et felis pulvinar, posuere sem non, porttitor eros.
231 `),
232 }
233 }
234
235 type mockDmsetupExec struct {
236 errOnCacheStatus bool
237 cacheStatusData []byte
238 }
239
240 func (m *mockDmsetupExec) cacheStatus() ([]byte, error) {
241 if m.errOnCacheStatus {
242 return nil, errors.New("mock.cacheStatus() error")
243 }
244
245 return m.cacheStatusData, nil
246 }