]> ruderich.org/simon Gitweb - safcm/safcm.git/blob - remote/sync/services_systemd_test.go
Use SPDX license identifiers
[safcm/safcm.git] / remote / sync / services_systemd_test.go
1 // SPDX-License-Identifier: GPL-3.0-or-later
2 // Copyright (C) 2021-2024  Simon Ruderich
3
4 package sync
5
6 import (
7         "bytes"
8         "fmt"
9         "os/exec"
10         "testing"
11
12         "ruderich.org/simon/safcm"
13         "ruderich.org/simon/safcm/testutil"
14 )
15
16 func TestSyncServicesSystemd(t *testing.T) {
17         tests := []struct {
18                 name    string
19                 req     safcm.MsgSyncReq
20                 stdout  [][]byte
21                 stderr  [][]byte
22                 errors  []error
23                 expCmds []*exec.Cmd
24                 expDbg  []string
25                 expResp safcm.MsgSyncResp
26                 expErr  error
27         }{
28
29                 // NOTE: Also update MsgSyncResp in safcm test cases when
30                 // changing the MsgSyncResp struct!
31
32                 {
33                         "no service change necessary",
34                         safcm.MsgSyncReq{
35                                 Services: []string{
36                                         "service-one",
37                                         "service-two",
38                                 },
39                         },
40                         [][]byte{
41                                 []byte(`ActiveState=active
42 UnitFileState=enabled
43 LoadError=
44
45 ActiveState=active
46 UnitFileState=enabled
47 LoadError=
48 `),
49                         },
50                         [][]byte{nil},
51                         []error{nil},
52                         []*exec.Cmd{{
53                                 Path: "/bin/systemctl",
54                                 Args: []string{
55                                         "/bin/systemctl",
56                                         "show",
57                                         "--property=ActiveState,UnitFileState,LoadError",
58                                         "--",
59                                         "service-one",
60                                         "service-two",
61                                 },
62                                 Stdout: &bytes.Buffer{},
63                                 Stderr: &bytes.Buffer{},
64                         }},
65                         []string{
66                                 "4: services: checking service-one service-two (systemd detected)",
67                                 `4: services: running "/bin/systemctl" "show" "--property=ActiveState,UnitFileState,LoadError" "--" "service-one" "service-two"`,
68                                 `5: services: command stdout:
69 ActiveState=active
70 UnitFileState=enabled
71 LoadError=
72
73 ActiveState=active
74 UnitFileState=enabled
75 LoadError=
76 `,
77                         },
78                         safcm.MsgSyncResp{},
79                         nil,
80                 },
81
82                 {
83                         "no service change necessary (older systemd)",
84                         safcm.MsgSyncReq{
85                                 Services: []string{
86                                         "service-one",
87                                         "service-two",
88                                 },
89                         },
90                         [][]byte{
91                                 []byte(`ActiveState=active
92 UnitFileState=enabled
93 LoadError= ""
94
95 ActiveState=active
96 UnitFileState=enabled
97 LoadError= ""
98 `),
99                         },
100                         [][]byte{nil},
101                         []error{nil},
102                         []*exec.Cmd{{
103                                 Path: "/bin/systemctl",
104                                 Args: []string{
105                                         "/bin/systemctl",
106                                         "show",
107                                         "--property=ActiveState,UnitFileState,LoadError",
108                                         "--",
109                                         "service-one",
110                                         "service-two",
111                                 },
112                                 Stdout: &bytes.Buffer{},
113                                 Stderr: &bytes.Buffer{},
114                         }},
115                         []string{
116                                 "4: services: checking service-one service-two (systemd detected)",
117                                 `4: services: running "/bin/systemctl" "show" "--property=ActiveState,UnitFileState,LoadError" "--" "service-one" "service-two"`,
118                                 `5: services: command stdout:
119 ActiveState=active
120 UnitFileState=enabled
121 LoadError= ""
122
123 ActiveState=active
124 UnitFileState=enabled
125 LoadError= ""
126 `,
127                         },
128                         safcm.MsgSyncResp{},
129                         nil,
130                 },
131
132                 {
133                         "invalid service",
134                         safcm.MsgSyncReq{
135                                 Services: []string{
136                                         "service-does-not-exist",
137                                         "service-two",
138                                 },
139                         },
140                         [][]byte{
141                                 []byte(`ActiveState=inactive
142 UnitFileState=
143 LoadError=org.freedesktop.systemd1.NoSuchUnit "Unit service-does-not-exist.service not found."
144
145 ActiveState=active
146 UnitFileState=enabled
147 LoadError=
148 `),
149                         },
150                         [][]byte{nil},
151                         []error{nil},
152                         []*exec.Cmd{{
153                                 Path: "/bin/systemctl",
154                                 Args: []string{
155                                         "/bin/systemctl",
156                                         "show",
157                                         "--property=ActiveState,UnitFileState,LoadError",
158                                         "--",
159                                         "service-does-not-exist",
160                                         "service-two",
161                                 },
162                                 Stdout: &bytes.Buffer{},
163                                 Stderr: &bytes.Buffer{},
164                         }},
165                         []string{
166                                 "4: services: checking service-does-not-exist service-two (systemd detected)",
167                                 `4: services: running "/bin/systemctl" "show" "--property=ActiveState,UnitFileState,LoadError" "--" "service-does-not-exist" "service-two"`,
168                                 `5: services: command stdout:
169 ActiveState=inactive
170 UnitFileState=
171 LoadError=org.freedesktop.systemd1.NoSuchUnit "Unit service-does-not-exist.service not found."
172
173 ActiveState=active
174 UnitFileState=enabled
175 LoadError=
176 `,
177                         },
178                         safcm.MsgSyncResp{},
179                         fmt.Errorf("systemd unit \"service-does-not-exist\" not found"),
180                 },
181
182                 {
183                         "start/enable service",
184                         safcm.MsgSyncReq{
185                                 Services: []string{
186                                         "service-one",
187                                         "service-two",
188                                         "service-three",
189                                 },
190                         },
191                         [][]byte{
192                                 []byte(`ActiveState=inactive
193 UnitFileState=enabled
194 LoadError=
195
196 ActiveState=active
197 UnitFileState=disabled
198 LoadError=
199
200 ActiveState=failed
201 UnitFileState=disabled
202 LoadError=
203 `),
204                                 nil,
205                                 nil,
206                                 nil,
207                         },
208                         [][]byte{
209                                 nil,
210                                 nil,
211                                 nil,
212                                 []byte("fake stderr"),
213                         },
214                         []error{nil, nil, nil, nil},
215                         []*exec.Cmd{{
216                                 Path: "/bin/systemctl",
217                                 Args: []string{
218                                         "/bin/systemctl",
219                                         "show",
220                                         "--property=ActiveState,UnitFileState,LoadError",
221                                         "--",
222                                         "service-one",
223                                         "service-two",
224                                         "service-three",
225                                 },
226                                 Stdout: &bytes.Buffer{},
227                                 Stderr: &bytes.Buffer{},
228                         }, {
229                                 Path: "/bin/systemctl",
230                                 Args: []string{
231                                         "/bin/systemctl",
232                                         "daemon-reload",
233                                 },
234                                 Stdout: &bytes.Buffer{},
235                                 Stderr: &bytes.Buffer{},
236                         }, {
237                                 Path: "/bin/systemctl",
238                                 Args: []string{
239                                         "/bin/systemctl",
240                                         "start",
241                                         "--",
242                                         "service-one",
243                                         "service-three",
244                                 },
245                                 Stdout: &bytes.Buffer{},
246                                 Stderr: &bytes.Buffer{},
247                         }, {
248                                 Path: "/bin/systemctl",
249                                 Args: []string{
250                                         "/bin/systemctl",
251                                         "enable",
252                                         "--",
253                                         "service-two",
254                                         "service-three",
255                                 },
256                                 Stdout: &bytes.Buffer{},
257                                 Stderr: &bytes.Buffer{},
258                         }},
259                         []string{
260                                 "4: services: checking service-one service-two service-three (systemd detected)",
261                                 `4: services: running "/bin/systemctl" "show" "--property=ActiveState,UnitFileState,LoadError" "--" "service-one" "service-two" "service-three"`,
262                                 `5: services: command stdout:
263 ActiveState=inactive
264 UnitFileState=enabled
265 LoadError=
266
267 ActiveState=active
268 UnitFileState=disabled
269 LoadError=
270
271 ActiveState=failed
272 UnitFileState=disabled
273 LoadError=
274 `,
275                                 `4: services: running "/bin/systemctl" "daemon-reload"`,
276                                 "3: services: starting service-one service-three",
277                                 `4: services: running "/bin/systemctl" "start" "--" "service-one" "service-three"`,
278                                 "3: services: enabling service-two service-three",
279                                 `4: services: running "/bin/systemctl" "enable" "--" "service-two" "service-three"`,
280                                 "5: services: command stderr:\nfake stderr",
281                         },
282                         safcm.MsgSyncResp{
283                                 ServiceChanges: []safcm.ServiceChange{
284                                         {
285                                                 Name:    "service-one",
286                                                 Started: true,
287                                         },
288                                         {
289                                                 Name:    "service-two",
290                                                 Enabled: true,
291                                         },
292                                         {
293                                                 Name:    "service-three",
294                                                 Started: true,
295                                                 Enabled: true,
296                                         },
297                                 },
298                         },
299                         nil,
300                 },
301
302                 {
303                         "start/enable service (dry-run)",
304                         safcm.MsgSyncReq{
305                                 DryRun: true,
306                                 Services: []string{
307                                         "service-one",
308                                         "service-two",
309                                         "service-three",
310                                 },
311                         },
312                         [][]byte{
313                                 []byte(`ActiveState=inactive
314 UnitFileState=enabled
315 LoadError=
316
317 ActiveState=active
318 UnitFileState=disabled
319 LoadError=
320
321 ActiveState=failed
322 UnitFileState=disabled
323 LoadError=
324 `),
325                         },
326                         [][]byte{nil},
327                         []error{nil},
328                         []*exec.Cmd{{
329                                 Path: "/bin/systemctl",
330                                 Args: []string{
331                                         "/bin/systemctl",
332                                         "show",
333                                         "--property=ActiveState,UnitFileState,LoadError",
334                                         "--",
335                                         "service-one",
336                                         "service-two",
337                                         "service-three",
338                                 },
339                                 Stdout: &bytes.Buffer{},
340                                 Stderr: &bytes.Buffer{},
341                         }},
342                         []string{
343                                 "4: services: checking service-one service-two service-three (systemd detected)",
344                                 `4: services: running "/bin/systemctl" "show" "--property=ActiveState,UnitFileState,LoadError" "--" "service-one" "service-two" "service-three"`,
345                                 `5: services: command stdout:
346 ActiveState=inactive
347 UnitFileState=enabled
348 LoadError=
349
350 ActiveState=active
351 UnitFileState=disabled
352 LoadError=
353
354 ActiveState=failed
355 UnitFileState=disabled
356 LoadError=
357 `,
358                         },
359                         safcm.MsgSyncResp{
360                                 ServiceChanges: []safcm.ServiceChange{
361                                         {
362                                                 Name:    "service-one",
363                                                 Started: true,
364                                         },
365                                         {
366                                                 Name:    "service-two",
367                                                 Enabled: true,
368                                         },
369                                         {
370                                                 Name:    "service-three",
371                                                 Started: true,
372                                                 Enabled: true,
373                                         },
374                                 },
375                         },
376                         nil,
377                 },
378
379                 {
380                         "start/enable service (error)",
381                         safcm.MsgSyncReq{
382                                 Services: []string{
383                                         "service-one",
384                                         "service-two",
385                                         "service-three",
386                                 },
387                         },
388                         [][]byte{
389                                 []byte(`ActiveState=inactive
390 UnitFileState=enabled
391 LoadError=
392
393 ActiveState=active
394 UnitFileState=disabled
395 LoadError=
396
397 ActiveState=failed
398 UnitFileState=disabled
399 LoadError=
400 `),
401                                 nil,
402                                 nil,
403                         },
404                         [][]byte{
405                                 nil,
406                                 nil,
407                                 []byte("fake stderr"),
408                         },
409                         []error{
410                                 nil,
411                                 nil,
412                                 fmt.Errorf("fake error"),
413                         },
414                         []*exec.Cmd{{
415                                 Path: "/bin/systemctl",
416                                 Args: []string{
417                                         "/bin/systemctl",
418                                         "show",
419                                         "--property=ActiveState,UnitFileState,LoadError",
420                                         "--",
421                                         "service-one",
422                                         "service-two",
423                                         "service-three",
424                                 },
425                                 Stdout: &bytes.Buffer{},
426                                 Stderr: &bytes.Buffer{},
427                         }, {
428                                 Path: "/bin/systemctl",
429                                 Args: []string{
430                                         "/bin/systemctl",
431                                         "daemon-reload",
432                                 },
433                                 Stdout: &bytes.Buffer{},
434                                 Stderr: &bytes.Buffer{},
435                         }, {
436                                 Path: "/bin/systemctl",
437                                 Args: []string{
438                                         "/bin/systemctl",
439                                         "start",
440                                         "--",
441                                         "service-one",
442                                         "service-three",
443                                 },
444                                 Stdout: &bytes.Buffer{},
445                                 Stderr: &bytes.Buffer{},
446                         }},
447                         []string{
448                                 "4: services: checking service-one service-two service-three (systemd detected)",
449                                 `4: services: running "/bin/systemctl" "show" "--property=ActiveState,UnitFileState,LoadError" "--" "service-one" "service-two" "service-three"`,
450                                 `5: services: command stdout:
451 ActiveState=inactive
452 UnitFileState=enabled
453 LoadError=
454
455 ActiveState=active
456 UnitFileState=disabled
457 LoadError=
458
459 ActiveState=failed
460 UnitFileState=disabled
461 LoadError=
462 `,
463                                 `4: services: running "/bin/systemctl" "daemon-reload"`,
464                                 "3: services: starting service-one service-three",
465                                 `4: services: running "/bin/systemctl" "start" "--" "service-one" "service-three"`,
466                                 "5: services: command stderr:\nfake stderr",
467                         },
468                         safcm.MsgSyncResp{
469                                 ServiceChanges: []safcm.ServiceChange{
470                                         {
471                                                 Name:    "service-one",
472                                                 Started: true,
473                                         },
474                                         {
475                                                 Name:    "service-two",
476                                                 Enabled: true,
477                                         },
478                                         {
479                                                 Name:    "service-three",
480                                                 Started: true,
481                                                 Enabled: true,
482                                         },
483                                 },
484                         },
485                         fmt.Errorf(`"/bin/systemctl" "start" "--" "service-one" "service-three" failed: fake error; stdout: "", stderr: "fake stderr"`),
486                 },
487         }
488
489         for _, tc := range tests {
490                 t.Run(tc.name, func(t *testing.T) {
491                         s, res := prepareSync(tc.req, &testRunner{
492                                 t:         t,
493                                 expCmds:   tc.expCmds,
494                                 resStdout: tc.stdout,
495                                 resStderr: tc.stderr,
496                                 resError:  tc.errors,
497                         })
498
499                         err := s.syncServicesSystemd()
500                         testutil.AssertErrorEqual(t, "err", err, tc.expErr)
501                         dbg := res.Wait()
502
503                         testutil.AssertEqual(t, "resp", s.resp, tc.expResp)
504                         testutil.AssertEqual(t, "dbg", dbg, tc.expDbg)
505                 })
506         }
507 }