blob: f9bc5c032f3b12a704eaf2b31e82b910c0c6dcd0 [file]
# Copyright 2026 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Unit tests for daemon service discovery and management."""
from __future__ import annotations
import io
import pathlib
import tempfile
import unittest
from unittest import mock
from agents.lib import services
class ServicesTest(unittest.TestCase):
"""Hermetic unit tests for daemon service discovery and restart."""
def setUp(self) -> None:
self.stdout_patch = mock.patch("sys.stdout", new_callable=io.StringIO)
self.mock_stdout = self.stdout_patch.start()
self.addCleanup(self.stdout_patch.stop)
self.stderr_patch = mock.patch("sys.stderr", new_callable=io.StringIO)
self.mock_stderr = self.stderr_patch.start()
self.addCleanup(self.stderr_patch.stop)
self.temp_dir = tempfile.TemporaryDirectory()
self.addCleanup(self.temp_dir.cleanup)
self.mock_root = pathlib.Path(self.temp_dir.name)
def test_find_daemon_services(self) -> None:
fuchsia_dir = self.mock_root
public_cfg = fuchsia_dir / ".agents" / "config"
public_cfg.mkdir(parents=True, exist_ok=True)
(public_cfg / "services.txt").write_text(
"service_a\nservice_b\n# comment\n", encoding="utf-8"
)
vendor_cfg = fuchsia_dir / "vendor" / "google" / ".agents" / "config"
vendor_cfg.mkdir(parents=True, exist_ok=True)
(vendor_cfg / "services.txt").write_text(
"service_c\nservice_a\n", encoding="utf-8"
)
found = services.find_daemon_services(fuchsia_dir)
self.assertEqual(found, ["service_a", "service_b", "service_c"])
def test_restart_daemons_dry_run(self) -> None:
with mock.patch("shutil.which", return_value="/bin/systemctl"):
with mock.patch("subprocess.run") as mock_run:
services.restart_daemons(["foo-service"], dry_run=True)
mock_run.assert_not_called()
self.assertIn(
"Would run: systemctl --user try-restart foo-service",
self.mock_stdout.getvalue(),
)
def test_restart_daemons_actual(self) -> None:
with mock.patch("shutil.which", return_value="/bin/systemctl"):
with mock.patch("subprocess.run") as mock_run:
services.restart_daemons(["foo-service"], dry_run=False)
mock_run.assert_called_once_with(
["systemctl", "--user", "try-restart", "foo-service"],
capture_output=True,
check=False,
)
def test_restart_daemons_no_systemctl(self) -> None:
with mock.patch("shutil.which", return_value=None):
with mock.patch("subprocess.run") as mock_run:
services.restart_daemons(["service_a"])
mock_run.assert_not_called()
if __name__ == "__main__":
unittest.main()