master
go 458 lines 17.6 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package hpssa
4
5 import (
6 "context"
7 "errors"
8 "os"
9 "testing"
10
11 "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/collecttest"
12
13 "github.com/stretchr/testify/assert"
14 "github.com/stretchr/testify/require"
15 )
16
17 var (
18 dataConfigJSON, _ = os.ReadFile("testdata/config.json")
19 dataConfigYAML, _ = os.ReadFile("testdata/config.yaml")
20
21 dataP212andP410i, _ = os.ReadFile("testdata/ssacli-P212_P410i.txt")
22 dataP400ar, _ = os.ReadFile("testdata/ssacli-P400ar.txt")
23 dataP408ia, _ = os.ReadFile("testdata/ssacli-P408i-a.txt")
24 dataP400iUnassigned, _ = os.ReadFile("testdata/ssacli-P400i-unassigned.txt")
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 "dataP212andP410i": dataP212andP410i,
33 "dataP400ar": dataP400ar,
34 "dataP408ia": dataP408ia,
35 "dataP400iUnassigned": dataP400iUnassigned,
36 } {
37 require.NotNil(t, data, name)
38 }
39 }
40
41 func TestCollector_Init(t *testing.T) {
42 tests := map[string]struct {
43 config Config
44 wantFail bool
45 }{
46 "success with default config": {
47 wantFail: false,
48 config: New().Config,
49 },
50 }
51
52 for name, test := range tests {
53 t.Run(name, func(t *testing.T) {
54 collr := New()
55
56 if test.wantFail {
57 assert.Error(t, collr.Init(context.Background()))
58 } else {
59 assert.NoError(t, collr.Init(context.Background()))
60 }
61 })
62 }
63 }
64
65 func TestCollector_Cleanup(t *testing.T) {
66 tests := map[string]struct {
67 prepare func() *Collector
68 }{
69 "not initialized exec": {
70 prepare: func() *Collector {
71 return New()
72 },
73 },
74 "after check": {
75 prepare: func() *Collector {
76 collr := New()
77 collr.exec = prepareMockOkP212andP410i()
78 _ = collr.Check(context.Background())
79 return collr
80 },
81 },
82 "after collect": {
83 prepare: func() *Collector {
84 collr := New()
85 collr.exec = prepareMockOkP212andP410i()
86 _ = collr.Collect(context.Background())
87 return collr
88 },
89 },
90 }
91
92 for name, test := range tests {
93 t.Run(name, func(t *testing.T) {
94 collr := test.prepare()
95
96 assert.NotPanics(t, func() { collr.Cleanup(context.Background()) })
97 })
98 }
99 }
100
101 func TestCollector_Charts(t *testing.T) {
102 assert.NotNil(t, New().Charts())
103 }
104
105 func TestCollector_Check(t *testing.T) {
106 tests := map[string]struct {
107 prepareMock func() *mockSsacliExec
108 wantFail bool
109 }{
110 "success P212 and P410i": {
111 wantFail: false,
112 prepareMock: prepareMockOkP212andP410i,
113 },
114 "success P400ar": {
115 wantFail: false,
116 prepareMock: prepareMockOkP400ar,
117 },
118 "success P400i with Unassigned": {
119 wantFail: false,
120 prepareMock: prepareMockOkP400iUnassigned,
121 },
122 "fails if error on controllersInfo()": {
123 wantFail: true,
124 prepareMock: prepareMockErr,
125 },
126 "fails if empty response": {
127 wantFail: true,
128 prepareMock: prepareMockEmptyResponse,
129 },
130 "fails if unexpected response": {
131 wantFail: true,
132 prepareMock: prepareMockUnexpectedResponse,
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() *mockSsacliExec
154 wantMetrics map[string]int64
155 wantCharts int
156 }{
157 "success P212 and P410i": {
158 prepareMock: prepareMockOkP212andP410i,
159 wantCharts: (len(controllerChartsTmpl)*2 - 6) +
160 len(arrayChartsTmpl)*3 +
161 len(logicalDriveChartsTmpl)*3 +
162 len(physicalDriveChartsTmpl)*18,
163 wantMetrics: map[string]int64{
164 "array_A_cntrl_P212_slot_5_status_nok": 0,
165 "array_A_cntrl_P212_slot_5_status_ok": 1,
166 "array_A_cntrl_P410i_slot_0_status_nok": 0,
167 "array_A_cntrl_P410i_slot_0_status_ok": 1,
168 "array_B_cntrl_P410i_slot_0_status_nok": 0,
169 "array_B_cntrl_P410i_slot_0_status_ok": 1,
170 "cntrl_P212_slot_5_cache_battery_status_nok": 0,
171 "cntrl_P212_slot_5_cache_battery_status_ok": 0,
172 "cntrl_P212_slot_5_cache_presence_status_not_present": 0,
173 "cntrl_P212_slot_5_cache_presence_status_present": 1,
174 "cntrl_P212_slot_5_cache_status_nok": 0,
175 "cntrl_P212_slot_5_cache_status_ok": 1,
176 "cntrl_P212_slot_5_status_nok": 0,
177 "cntrl_P212_slot_5_status_ok": 1,
178 "cntrl_P410i_slot_0_cache_battery_status_nok": 0,
179 "cntrl_P410i_slot_0_cache_battery_status_ok": 0,
180 "cntrl_P410i_slot_0_cache_presence_status_not_present": 0,
181 "cntrl_P410i_slot_0_cache_presence_status_present": 1,
182 "cntrl_P410i_slot_0_cache_status_nok": 0,
183 "cntrl_P410i_slot_0_cache_status_ok": 1,
184 "cntrl_P410i_slot_0_status_nok": 0,
185 "cntrl_P410i_slot_0_status_ok": 1,
186 "ld_1_array_A_cntrl_P212_slot_5_status_nok": 0,
187 "ld_1_array_A_cntrl_P212_slot_5_status_ok": 1,
188 "ld_1_array_A_cntrl_P410i_slot_0_status_nok": 0,
189 "ld_1_array_A_cntrl_P410i_slot_0_status_ok": 1,
190 "ld_2_array_B_cntrl_P410i_slot_0_status_nok": 0,
191 "ld_2_array_B_cntrl_P410i_slot_0_status_ok": 1,
192 "pd_1I:1:1_ld_2_array_B_cntrl_P410i_slot_0_status_nok": 0,
193 "pd_1I:1:1_ld_2_array_B_cntrl_P410i_slot_0_status_ok": 1,
194 "pd_1I:1:1_ld_2_array_B_cntrl_P410i_slot_0_temperature": 37,
195 "pd_1I:1:2_ld_2_array_B_cntrl_P410i_slot_0_status_nok": 0,
196 "pd_1I:1:2_ld_2_array_B_cntrl_P410i_slot_0_status_ok": 1,
197 "pd_1I:1:2_ld_2_array_B_cntrl_P410i_slot_0_temperature": 37,
198 "pd_1I:1:3_ld_2_array_B_cntrl_P410i_slot_0_status_nok": 0,
199 "pd_1I:1:3_ld_2_array_B_cntrl_P410i_slot_0_status_ok": 1,
200 "pd_1I:1:3_ld_2_array_B_cntrl_P410i_slot_0_temperature": 43,
201 "pd_1I:1:4_ld_2_array_B_cntrl_P410i_slot_0_status_nok": 0,
202 "pd_1I:1:4_ld_2_array_B_cntrl_P410i_slot_0_status_ok": 1,
203 "pd_1I:1:4_ld_2_array_B_cntrl_P410i_slot_0_temperature": 44,
204 "pd_2E:1:10_ld_na_array_na_cntrl_P212_slot_5_status_nok": 0,
205 "pd_2E:1:10_ld_na_array_na_cntrl_P212_slot_5_status_ok": 1,
206 "pd_2E:1:10_ld_na_array_na_cntrl_P212_slot_5_temperature": 35,
207 "pd_2E:1:11_ld_na_array_na_cntrl_P212_slot_5_status_nok": 0,
208 "pd_2E:1:11_ld_na_array_na_cntrl_P212_slot_5_status_ok": 1,
209 "pd_2E:1:11_ld_na_array_na_cntrl_P212_slot_5_temperature": 34,
210 "pd_2E:1:12_ld_na_array_na_cntrl_P212_slot_5_status_nok": 0,
211 "pd_2E:1:12_ld_na_array_na_cntrl_P212_slot_5_status_ok": 1,
212 "pd_2E:1:12_ld_na_array_na_cntrl_P212_slot_5_temperature": 31,
213 "pd_2E:1:1_ld_1_array_A_cntrl_P212_slot_5_status_nok": 0,
214 "pd_2E:1:1_ld_1_array_A_cntrl_P212_slot_5_status_ok": 1,
215 "pd_2E:1:1_ld_1_array_A_cntrl_P212_slot_5_temperature": 33,
216 "pd_2E:1:2_ld_1_array_A_cntrl_P212_slot_5_status_nok": 0,
217 "pd_2E:1:2_ld_1_array_A_cntrl_P212_slot_5_status_ok": 1,
218 "pd_2E:1:2_ld_1_array_A_cntrl_P212_slot_5_temperature": 34,
219 "pd_2E:1:3_ld_1_array_A_cntrl_P212_slot_5_status_nok": 0,
220 "pd_2E:1:3_ld_1_array_A_cntrl_P212_slot_5_status_ok": 1,
221 "pd_2E:1:3_ld_1_array_A_cntrl_P212_slot_5_temperature": 35,
222 "pd_2E:1:4_ld_1_array_A_cntrl_P212_slot_5_status_nok": 0,
223 "pd_2E:1:4_ld_1_array_A_cntrl_P212_slot_5_status_ok": 1,
224 "pd_2E:1:4_ld_1_array_A_cntrl_P212_slot_5_temperature": 35,
225 "pd_2E:1:5_ld_1_array_A_cntrl_P212_slot_5_status_nok": 0,
226 "pd_2E:1:5_ld_1_array_A_cntrl_P212_slot_5_status_ok": 1,
227 "pd_2E:1:5_ld_1_array_A_cntrl_P212_slot_5_temperature": 34,
228 "pd_2E:1:6_ld_1_array_A_cntrl_P212_slot_5_status_nok": 0,
229 "pd_2E:1:6_ld_1_array_A_cntrl_P212_slot_5_status_ok": 1,
230 "pd_2E:1:6_ld_1_array_A_cntrl_P212_slot_5_temperature": 33,
231 "pd_2E:1:7_ld_na_array_na_cntrl_P212_slot_5_status_nok": 0,
232 "pd_2E:1:7_ld_na_array_na_cntrl_P212_slot_5_status_ok": 1,
233 "pd_2E:1:7_ld_na_array_na_cntrl_P212_slot_5_temperature": 30,
234 "pd_2E:1:8_ld_na_array_na_cntrl_P212_slot_5_status_nok": 0,
235 "pd_2E:1:8_ld_na_array_na_cntrl_P212_slot_5_status_ok": 1,
236 "pd_2E:1:8_ld_na_array_na_cntrl_P212_slot_5_temperature": 33,
237 "pd_2E:1:9_ld_na_array_na_cntrl_P212_slot_5_status_nok": 0,
238 "pd_2E:1:9_ld_na_array_na_cntrl_P212_slot_5_status_ok": 1,
239 "pd_2E:1:9_ld_na_array_na_cntrl_P212_slot_5_temperature": 30,
240 "pd_2I:1:5_ld_1_array_A_cntrl_P410i_slot_0_status_nok": 0,
241 "pd_2I:1:5_ld_1_array_A_cntrl_P410i_slot_0_status_ok": 1,
242 "pd_2I:1:5_ld_1_array_A_cntrl_P410i_slot_0_temperature": 38,
243 "pd_2I:1:6_ld_1_array_A_cntrl_P410i_slot_0_status_nok": 0,
244 "pd_2I:1:6_ld_1_array_A_cntrl_P410i_slot_0_status_ok": 1,
245 "pd_2I:1:6_ld_1_array_A_cntrl_P410i_slot_0_temperature": 36,
246 },
247 },
248 "success P400ar": {
249 prepareMock: prepareMockOkP400ar,
250 wantCharts: len(controllerChartsTmpl)*1 +
251 len(arrayChartsTmpl)*2 +
252 len(logicalDriveChartsTmpl)*2 +
253 len(physicalDriveChartsTmpl)*8,
254 wantMetrics: map[string]int64{
255 "array_A_cntrl_P440ar_slot_0_status_nok": 0,
256 "array_A_cntrl_P440ar_slot_0_status_ok": 1,
257 "array_B_cntrl_P440ar_slot_0_status_nok": 0,
258 "array_B_cntrl_P440ar_slot_0_status_ok": 1,
259 "cntrl_P440ar_slot_0_cache_battery_status_nok": 0,
260 "cntrl_P440ar_slot_0_cache_battery_status_ok": 1,
261 "cntrl_P440ar_slot_0_cache_presence_status_not_present": 0,
262 "cntrl_P440ar_slot_0_cache_presence_status_present": 1,
263 "cntrl_P440ar_slot_0_cache_status_nok": 0,
264 "cntrl_P440ar_slot_0_cache_status_ok": 1,
265 "cntrl_P440ar_slot_0_cache_temperature": 41,
266 "cntrl_P440ar_slot_0_status_nok": 0,
267 "cntrl_P440ar_slot_0_status_ok": 1,
268 "cntrl_P440ar_slot_0_temperature": 47,
269 "ld_1_array_A_cntrl_P440ar_slot_0_status_nok": 0,
270 "ld_1_array_A_cntrl_P440ar_slot_0_status_ok": 1,
271 "ld_2_array_B_cntrl_P440ar_slot_0_status_nok": 0,
272 "ld_2_array_B_cntrl_P440ar_slot_0_status_ok": 1,
273 "pd_1I:1:1_ld_1_array_A_cntrl_P440ar_slot_0_status_nok": 0,
274 "pd_1I:1:1_ld_1_array_A_cntrl_P440ar_slot_0_status_ok": 1,
275 "pd_1I:1:1_ld_1_array_A_cntrl_P440ar_slot_0_temperature": 27,
276 "pd_1I:1:2_ld_1_array_A_cntrl_P440ar_slot_0_status_nok": 0,
277 "pd_1I:1:2_ld_1_array_A_cntrl_P440ar_slot_0_status_ok": 1,
278 "pd_1I:1:2_ld_1_array_A_cntrl_P440ar_slot_0_temperature": 28,
279 "pd_1I:1:3_ld_1_array_A_cntrl_P440ar_slot_0_status_nok": 0,
280 "pd_1I:1:3_ld_1_array_A_cntrl_P440ar_slot_0_status_ok": 1,
281 "pd_1I:1:3_ld_1_array_A_cntrl_P440ar_slot_0_temperature": 27,
282 "pd_1I:1:4_ld_2_array_B_cntrl_P440ar_slot_0_status_nok": 0,
283 "pd_1I:1:4_ld_2_array_B_cntrl_P440ar_slot_0_status_ok": 1,
284 "pd_1I:1:4_ld_2_array_B_cntrl_P440ar_slot_0_temperature": 30,
285 "pd_2I:1:5_ld_1_array_A_cntrl_P440ar_slot_0_status_nok": 0,
286 "pd_2I:1:5_ld_1_array_A_cntrl_P440ar_slot_0_status_ok": 1,
287 "pd_2I:1:5_ld_1_array_A_cntrl_P440ar_slot_0_temperature": 26,
288 "pd_2I:1:6_ld_1_array_A_cntrl_P440ar_slot_0_status_nok": 0,
289 "pd_2I:1:6_ld_1_array_A_cntrl_P440ar_slot_0_status_ok": 1,
290 "pd_2I:1:6_ld_1_array_A_cntrl_P440ar_slot_0_temperature": 28,
291 "pd_2I:1:7_ld_1_array_A_cntrl_P440ar_slot_0_status_nok": 0,
292 "pd_2I:1:7_ld_1_array_A_cntrl_P440ar_slot_0_status_ok": 1,
293 "pd_2I:1:7_ld_1_array_A_cntrl_P440ar_slot_0_temperature": 27,
294 "pd_2I:1:8_ld_2_array_B_cntrl_P440ar_slot_0_status_nok": 0,
295 "pd_2I:1:8_ld_2_array_B_cntrl_P440ar_slot_0_status_ok": 1,
296 "pd_2I:1:8_ld_2_array_B_cntrl_P440ar_slot_0_temperature": 29,
297 },
298 },
299 "success P408i-a": {
300 prepareMock: prepareMockOkP408ia,
301 wantCharts: len(controllerChartsTmpl)*1 - 1 +
302 len(arrayChartsTmpl)*1 +
303 len(logicalDriveChartsTmpl)*1 +
304 len(physicalDriveChartsTmpl)*4,
305 wantMetrics: map[string]int64{
306 "array_A_cntrl_HPE_slot_P408i-a_status_nok": 0,
307 "array_A_cntrl_HPE_slot_P408i-a_status_ok": 1,
308 "cntrl_HPE_slot_P408i-a_cache_battery_status_nok": 0,
309 "cntrl_HPE_slot_P408i-a_cache_battery_status_ok": 1,
310 "cntrl_HPE_slot_P408i-a_cache_presence_status_not_present": 0,
311 "cntrl_HPE_slot_P408i-a_cache_presence_status_present": 1,
312 "cntrl_HPE_slot_P408i-a_cache_status_nok": 0,
313 "cntrl_HPE_slot_P408i-a_cache_status_ok": 1,
314 "cntrl_HPE_slot_P408i-a_status_nok": 0,
315 "cntrl_HPE_slot_P408i-a_status_ok": 1,
316 "cntrl_HPE_slot_P408i-a_temperature": 52,
317 "ld_1_array_A_cntrl_HPE_slot_P408i-a_status_nok": 0,
318 "ld_1_array_A_cntrl_HPE_slot_P408i-a_status_ok": 1,
319 "pd_2I:1:1_ld_1_array_A_cntrl_HPE_slot_P408i-a_status_nok": 0,
320 "pd_2I:1:1_ld_1_array_A_cntrl_HPE_slot_P408i-a_status_ok": 1,
321 "pd_2I:1:1_ld_1_array_A_cntrl_HPE_slot_P408i-a_temperature": 34,
322 "pd_2I:1:2_ld_1_array_A_cntrl_HPE_slot_P408i-a_status_nok": 0,
323 "pd_2I:1:2_ld_1_array_A_cntrl_HPE_slot_P408i-a_status_ok": 1,
324 "pd_2I:1:2_ld_1_array_A_cntrl_HPE_slot_P408i-a_temperature": 34,
325 "pd_2I:1:3_ld_1_array_A_cntrl_HPE_slot_P408i-a_status_nok": 0,
326 "pd_2I:1:3_ld_1_array_A_cntrl_HPE_slot_P408i-a_status_ok": 1,
327 "pd_2I:1:3_ld_1_array_A_cntrl_HPE_slot_P408i-a_temperature": 28,
328 "pd_2I:1:4_ld_1_array_A_cntrl_HPE_slot_P408i-a_status_nok": 0,
329 "pd_2I:1:4_ld_1_array_A_cntrl_HPE_slot_P408i-a_status_ok": 1,
330 "pd_2I:1:4_ld_1_array_A_cntrl_HPE_slot_P408i-a_temperature": 30,
331 },
332 },
333 "success P400i with Unassigned": {
334 prepareMock: prepareMockOkP400iUnassigned,
335 wantCharts: (len(controllerChartsTmpl)*1 - 2) +
336 len(arrayChartsTmpl)*1 +
337 len(logicalDriveChartsTmpl)*1 +
338 len(physicalDriveChartsTmpl)*4,
339 wantMetrics: map[string]int64{
340 "array_A_cntrl_P400i_slot_0_status_nok": 0,
341 "array_A_cntrl_P400i_slot_0_status_ok": 1,
342 "cntrl_P400i_slot_0_cache_battery_status_nok": 1,
343 "cntrl_P400i_slot_0_cache_battery_status_ok": 0,
344 "cntrl_P400i_slot_0_cache_presence_status_not_present": 0,
345 "cntrl_P400i_slot_0_cache_presence_status_present": 1,
346 "cntrl_P400i_slot_0_cache_status_nok": 1,
347 "cntrl_P400i_slot_0_cache_status_ok": 0,
348 "cntrl_P400i_slot_0_status_nok": 0,
349 "cntrl_P400i_slot_0_status_ok": 1,
350 "ld_1_array_A_cntrl_P400i_slot_0_status_nok": 0,
351 "ld_1_array_A_cntrl_P400i_slot_0_status_ok": 1,
352 "pd_1I:1:1_ld_na_array_na_cntrl_P400i_slot_0_status_nok": 0,
353 "pd_1I:1:1_ld_na_array_na_cntrl_P400i_slot_0_status_ok": 1,
354 "pd_1I:1:1_ld_na_array_na_cntrl_P400i_slot_0_temperature": 28,
355 "pd_1I:1:2_ld_na_array_na_cntrl_P400i_slot_0_status_nok": 0,
356 "pd_1I:1:2_ld_na_array_na_cntrl_P400i_slot_0_status_ok": 1,
357 "pd_1I:1:2_ld_na_array_na_cntrl_P400i_slot_0_temperature": 28,
358 "pd_1I:1:3_ld_1_array_A_cntrl_P400i_slot_0_status_nok": 0,
359 "pd_1I:1:3_ld_1_array_A_cntrl_P400i_slot_0_status_ok": 1,
360 "pd_1I:1:3_ld_1_array_A_cntrl_P400i_slot_0_temperature": 23,
361 "pd_1I:1:4_ld_1_array_A_cntrl_P400i_slot_0_status_nok": 0,
362 "pd_1I:1:4_ld_1_array_A_cntrl_P400i_slot_0_status_ok": 1,
363 "pd_1I:1:4_ld_1_array_A_cntrl_P400i_slot_0_temperature": 23,
364 },
365 },
366 "fails if error on controllersInfo()": {
367 prepareMock: prepareMockErr,
368 wantMetrics: nil,
369 wantCharts: 0,
370 },
371 "fails if empty response": {
372 prepareMock: prepareMockEmptyResponse,
373 wantMetrics: nil,
374 wantCharts: 0,
375 },
376 "fails if unexpected response": {
377 prepareMock: prepareMockUnexpectedResponse,
378 wantMetrics: nil,
379 wantCharts: 0,
380 },
381 }
382
383 for name, test := range tests {
384 t.Run(name, func(t *testing.T) {
385 collr := New()
386 mock := test.prepareMock()
387 collr.exec = mock
388
389 mx := collr.Collect(context.Background())
390
391 assert.Equal(t, test.wantMetrics, mx)
392
393 assert.Len(t, *collr.Charts(), test.wantCharts, "wantCharts")
394
395 collecttest.TestMetricsHasAllChartsDims(t, collr.Charts(), mx)
396 })
397 }
398 }
399
400 func TestCollector_ConfigurationSerialize(t *testing.T) {
401 collecttest.TestConfigurationSerialize(t, &Collector{}, dataConfigJSON, dataConfigYAML)
402 }
403
404 func prepareMockOkP212andP410i() *mockSsacliExec {
405 return &mockSsacliExec{
406 infoData: dataP212andP410i,
407 }
408 }
409
410 func prepareMockOkP400ar() *mockSsacliExec {
411 return &mockSsacliExec{
412 infoData: dataP400ar,
413 }
414 }
415 func prepareMockOkP408ia() *mockSsacliExec {
416 return &mockSsacliExec{
417 infoData: dataP408ia,
418 }
419 }
420
421 func prepareMockOkP400iUnassigned() *mockSsacliExec {
422 return &mockSsacliExec{
423 infoData: dataP400iUnassigned,
424 }
425 }
426
427 func prepareMockErr() *mockSsacliExec {
428 return &mockSsacliExec{
429 errOnInfo: true,
430 }
431 }
432
433 func prepareMockEmptyResponse() *mockSsacliExec {
434 return &mockSsacliExec{}
435 }
436
437 func prepareMockUnexpectedResponse() *mockSsacliExec {
438 resp := []byte(`
439 Lorem ipsum dolor sit amet, consectetur adipiscing elit.
440 Nulla malesuada erat id magna mattis, eu viverra tellus rhoncus.
441 Fusce et felis pulvinar, posuere sem non, porttitor eros.
442 `)
443 return &mockSsacliExec{
444 infoData: resp,
445 }
446 }
447
448 type mockSsacliExec struct {
449 errOnInfo bool
450 infoData []byte
451 }
452
453 func (m *mockSsacliExec) controllersInfo() ([]byte, error) {
454 if m.errOnInfo {
455 return nil, errors.New("mock.controllersInfo() error")
456 }
457 return m.infoData, nil
458 }