master
go 240 lines 5.14 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 //go:build linux || netbsd
4
5 package lvm
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 dataLvsReportJson, _ = os.ReadFile("testdata/lvs-report.json")
24 dataLvsReportNoThinJson, _ = os.ReadFile("testdata/lvs-report-no-thin.json")
25 )
26
27 func Test_testDataIsValid(t *testing.T) {
28 for name, data := range map[string][]byte{
29 "dataConfigJSON": dataConfigJSON,
30 "dataConfigYAML": dataConfigYAML,
31
32 "dataLvsReportJson": dataLvsReportJson,
33 "dataLvsReportNoThinJson": dataLvsReportNoThinJson,
34 } {
35 require.NotNil(t, data, name)
36
37 }
38 }
39
40 func TestCollector_Configuration(t *testing.T) {
41 collecttest.TestConfigurationSerialize(t, &Collector{}, dataConfigJSON, dataConfigYAML)
42 }
43
44 func TestCollector_Init(t *testing.T) {
45 tests := map[string]struct {
46 config Config
47 wantFail bool
48 }{
49 "success with default config": {
50 wantFail: false,
51 config: New().Config,
52 },
53 }
54
55 for name, test := range tests {
56 t.Run(name, func(t *testing.T) {
57 collr := New()
58 collr.Config = test.config
59
60 if test.wantFail {
61 assert.Error(t, collr.Init(context.Background()))
62 } else {
63 assert.NoError(t, collr.Init(context.Background()))
64 }
65 })
66 }
67 }
68
69 func TestCollector_Cleanup(t *testing.T) {
70 tests := map[string]struct {
71 prepare func() *Collector
72 }{
73 "not initialized exec": {
74 prepare: func() *Collector {
75 return New()
76 },
77 },
78 "after check": {
79 prepare: func() *Collector {
80 collr := New()
81 collr.exec = prepareMockOK()
82 _ = collr.Check(context.Background())
83 return collr
84 },
85 },
86 "after collect": {
87 prepare: func() *Collector {
88 collr := New()
89 collr.exec = prepareMockOK()
90 _ = collr.Collect(context.Background())
91 return collr
92 },
93 },
94 }
95
96 for name, test := range tests {
97 t.Run(name, func(t *testing.T) {
98 collr := test.prepare()
99
100 assert.NotPanics(t, func() { collr.Cleanup(context.Background()) })
101 })
102 }
103 }
104
105 func TestCollector_Charts(t *testing.T) {
106 assert.NotNil(t, New().Charts())
107 }
108
109 func TestCollector_Check(t *testing.T) {
110 tests := map[string]struct {
111 prepareMock func() *mockLvmCliExec
112 wantFail bool
113 }{
114 "success case": {
115 prepareMock: prepareMockOK,
116 wantFail: false,
117 },
118 "no thin volumes": {
119 prepareMock: prepareMockNoThinVolumes,
120 wantFail: true,
121 },
122 "error on lvs report call": {
123 prepareMock: prepareMockErrOnLvsReportJson,
124 wantFail: true,
125 },
126 "empty response": {
127 prepareMock: prepareMockEmptyResponse,
128 wantFail: true,
129 },
130 "unexpected response": {
131 prepareMock: prepareMockUnexpectedResponse,
132 wantFail: true,
133 },
134 }
135
136 for name, test := range tests {
137 t.Run(name, func(t *testing.T) {
138 collr := New()
139 mock := test.prepareMock()
140 collr.exec = mock
141
142 if test.wantFail {
143 assert.Error(t, collr.Check(context.Background()))
144 } else {
145 assert.NoError(t, collr.Check(context.Background()))
146 }
147 })
148 }
149 }
150
151 func TestCollector_Collect(t *testing.T) {
152 tests := map[string]struct {
153 prepareMock func() *mockLvmCliExec
154 wantMetrics map[string]int64
155 }{
156 "success case": {
157 prepareMock: prepareMockOK,
158 wantMetrics: map[string]int64{
159 "lv_root_vg_cm-vg_data_percent": 7889,
160 "lv_root_vg_cm-vg_metadata_percent": 1925,
161 },
162 },
163 "no thin volumes": {
164 prepareMock: prepareMockNoThinVolumes,
165 wantMetrics: nil,
166 },
167 "error on lvs report call": {
168 prepareMock: prepareMockErrOnLvsReportJson,
169 wantMetrics: nil,
170 },
171 "empty response": {
172 prepareMock: prepareMockEmptyResponse,
173 wantMetrics: nil,
174 },
175 "unexpected response": {
176 prepareMock: prepareMockUnexpectedResponse,
177 wantMetrics: nil,
178 },
179 }
180
181 for name, test := range tests {
182 t.Run(name, func(t *testing.T) {
183 collr := New()
184 mock := test.prepareMock()
185 collr.exec = mock
186
187 mx := collr.Collect(context.Background())
188
189 assert.Equal(t, test.wantMetrics, mx)
190 if len(test.wantMetrics) > 0 {
191 assert.Len(t, *collr.Charts(), len(lvThinPoolChartsTmpl)*len(collr.lvmThinPools))
192 }
193 })
194 }
195 }
196
197 func prepareMockOK() *mockLvmCliExec {
198 return &mockLvmCliExec{
199 lvsReportJsonData: dataLvsReportJson,
200 }
201 }
202
203 func prepareMockNoThinVolumes() *mockLvmCliExec {
204 return &mockLvmCliExec{
205 lvsReportJsonData: dataLvsReportNoThinJson,
206 }
207 }
208
209 func prepareMockErrOnLvsReportJson() *mockLvmCliExec {
210 return &mockLvmCliExec{
211 errOnLvsReportJson: true,
212 }
213 }
214
215 func prepareMockEmptyResponse() *mockLvmCliExec {
216 return &mockLvmCliExec{}
217 }
218
219 func prepareMockUnexpectedResponse() *mockLvmCliExec {
220 return &mockLvmCliExec{
221 lvsReportJsonData: []byte(`
222 Lorem ipsum dolor sit amet, consectetur adipiscing elit.
223 Nulla malesuada erat id magna mattis, eu viverra tellus rhoncus.
224 Fusce et felis pulvinar, posuere sem non, porttitor eros.
225 `),
226 }
227 }
228
229 type mockLvmCliExec struct {
230 errOnLvsReportJson bool
231 lvsReportJsonData []byte
232 }
233
234 func (m *mockLvmCliExec) lvsReportJson() ([]byte, error) {
235 if m.errOnLvsReportJson {
236 return nil, errors.New("mock.lvsReportJson() error")
237 }
238
239 return m.lvsReportJsonData, nil
240 }