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