1 // Copyright (C) 2021 Simon Ruderich
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.
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.
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/>.
25 "github.com/google/go-cmp/cmp"
27 "ruderich.org/simon/safcm"
30 func TestSyncServicesSystemd(t *testing.T) {
39 expResp safcm.MsgSyncResp
43 // NOTE: Also update MsgSyncResp in safcm test cases when
44 // changing anything here!
47 "no service change necessary",
55 []byte(`ActiveState=active
66 []*exec.Cmd{&exec.Cmd{
67 Path: "/bin/systemctl",
71 "--property=ActiveState,UnitFileState,LoadError",
76 Stdout: &bytes.Buffer{},
77 Stderr: &bytes.Buffer{},
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:
98 "no service change necessary (older systemd)",
106 []byte(`ActiveState=active
107 UnitFileState=enabled
111 UnitFileState=enabled
117 []*exec.Cmd{&exec.Cmd{
118 Path: "/bin/systemctl",
122 "--property=ActiveState,UnitFileState,LoadError",
127 Stdout: &bytes.Buffer{},
128 Stderr: &bytes.Buffer{},
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:
136 UnitFileState=enabled
140 UnitFileState=enabled
152 "service-does-not-exist",
157 []byte(`ActiveState=inactive
159 LoadError=org.freedesktop.systemd1.NoSuchUnit "Unit service-does-not-exist.service not found."
162 UnitFileState=enabled
168 []*exec.Cmd{&exec.Cmd{
169 Path: "/bin/systemctl",
173 "--property=ActiveState,UnitFileState,LoadError",
175 "service-does-not-exist",
178 Stdout: &bytes.Buffer{},
179 Stderr: &bytes.Buffer{},
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:
188 LoadError=org.freedesktop.systemd1.NoSuchUnit "Unit service-does-not-exist.service not found."
191 UnitFileState=enabled
196 fmt.Errorf("systemd unit \"service-does-not-exist\" not found"),
200 "start/enable service",
209 []byte(`ActiveState=inactive
210 UnitFileState=enabled
214 UnitFileState=disabled
218 UnitFileState=disabled
229 []byte(`fake stderr`),
231 []error{nil, nil, nil, nil},
232 []*exec.Cmd{&exec.Cmd{
233 Path: "/bin/systemctl",
237 "--property=ActiveState,UnitFileState,LoadError",
243 Stdout: &bytes.Buffer{},
244 Stderr: &bytes.Buffer{},
246 Path: "/bin/systemctl",
251 Stdout: &bytes.Buffer{},
252 Stderr: &bytes.Buffer{},
254 Path: "/bin/systemctl",
262 Stdout: &bytes.Buffer{},
263 Stderr: &bytes.Buffer{},
265 Path: "/bin/systemctl",
273 Stdout: &bytes.Buffer{},
274 Stderr: &bytes.Buffer{},
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:
282 UnitFileState=enabled
286 UnitFileState=disabled
290 UnitFileState=disabled
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",
301 ServiceChanges: []safcm.ServiceChange{
311 Name: "service-three",
321 "start/enable service (dry-run)",
331 []byte(`ActiveState=inactive
332 UnitFileState=enabled
336 UnitFileState=disabled
340 UnitFileState=disabled
346 []*exec.Cmd{&exec.Cmd{
347 Path: "/bin/systemctl",
351 "--property=ActiveState,UnitFileState,LoadError",
357 Stdout: &bytes.Buffer{},
358 Stderr: &bytes.Buffer{},
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:
366 UnitFileState=enabled
370 UnitFileState=disabled
374 UnitFileState=disabled
379 ServiceChanges: []safcm.ServiceChange{
389 Name: "service-three",
399 "start/enable service (error)",
408 []byte(`ActiveState=inactive
409 UnitFileState=enabled
413 UnitFileState=disabled
417 UnitFileState=disabled
426 []byte(`fake stderr`),
431 fmt.Errorf("fake error"),
433 []*exec.Cmd{&exec.Cmd{
434 Path: "/bin/systemctl",
438 "--property=ActiveState,UnitFileState,LoadError",
444 Stdout: &bytes.Buffer{},
445 Stderr: &bytes.Buffer{},
447 Path: "/bin/systemctl",
452 Stdout: &bytes.Buffer{},
453 Stderr: &bytes.Buffer{},
455 Path: "/bin/systemctl",
463 Stdout: &bytes.Buffer{},
464 Stderr: &bytes.Buffer{},
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:
472 UnitFileState=enabled
476 UnitFileState=disabled
480 UnitFileState=disabled
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",
489 ServiceChanges: []safcm.ServiceChange{
499 Name: "service-three",
505 fmt.Errorf(`"/bin/systemctl" "start" "--" "service-one" "service-three" failed: fake error; stdout: "", stderr: "fake stderr"`),
509 for _, tc := range tests {
510 s, res := prepareSync(tc.req, &testRunner{
514 resStdout: tc.stdout,
515 resStderr: tc.stderr,
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("%s: err = %#v, want %#v",
523 tc.name, err, tc.expErr)
527 if !reflect.DeepEqual(tc.expResp, s.resp) {
528 t.Errorf("%s: resp: %s", tc.name,
529 cmp.Diff(tc.expResp, s.resp))
531 if !reflect.DeepEqual(tc.expDbg, dbg) {
532 t.Errorf("%s: dbg: %s", tc.name,
533 cmp.Diff(tc.expDbg, dbg))