1"""
2integration tests for mac_service
3"""
4
5import plistlib
6
7import pytest
8import salt.utils.files
9from tests.support.case import ModuleCase
10from tests.support.helpers import runs_on
11
12
13@pytest.mark.skip_if_not_root
14@runs_on(kernel="Darwin")
15@pytest.mark.skip_if_binaries_missing("launchctl", "plutil")
16class MacServiceModuleTest(ModuleCase):
17    """
18    Validate the mac_service module
19    """
20
21    SERVICE_NAME = "com.salt.integration.test"
22    SERVICE_PATH = "/Library/LaunchDaemons/com.salt.integration.test.plist"
23
24    def setUp(self):
25        """
26        setup our test launch service.
27        """
28        service_data = {
29            "KeepAlive": True,
30            "Label": self.SERVICE_NAME,
31            "ProgramArguments": ["/bin/sleep", "1000"],
32            "RunAtLoad": True,
33        }
34        with salt.utils.files.fopen(self.SERVICE_PATH, "wb") as fp:
35            plistlib.dump(service_data, fp)
36        self.run_function("service.enable", [self.SERVICE_NAME])
37        self.run_function("service.start", [self.SERVICE_NAME])
38
39    def tearDown(self):
40        """
41        stop and remove our test service.
42        """
43        self.run_function("service.stop", [self.SERVICE_NAME])
44        salt.utils.files.safe_rm(self.SERVICE_PATH)
45
46    @pytest.mark.slow_test
47    def test_show(self):
48        """
49        Test service.show
50        """
51        # Existing Service
52        service_info = self.run_function("service.show", [self.SERVICE_NAME])
53        self.assertIsInstance(service_info, dict)
54        self.assertEqual(service_info["plist"]["Label"], self.SERVICE_NAME)
55
56        # Missing Service
57        self.assertIn(
58            "Service not found", self.run_function("service.show", ["spongebob"])
59        )
60
61    @pytest.mark.slow_test
62    def test_launchctl(self):
63        """
64        Test service.launchctl
65        """
66        # Expected Functionality
67        self.assertTrue(
68            self.run_function("service.launchctl", ["error", "bootstrap", 64])
69        )
70        self.assertEqual(
71            self.run_function(
72                "service.launchctl", ["error", "bootstrap", 64], return_stdout=True
73            ),
74            "64: unknown error code",
75        )
76
77        # Raise an error
78        self.assertIn(
79            "Failed to error service",
80            self.run_function("service.launchctl", ["error", "bootstrap"]),
81        )
82
83    @pytest.mark.slow_test
84    def test_list(self):
85        """
86        Test service.list
87        """
88        # Expected Functionality
89        self.assertIn("PID", self.run_function("service.list"))
90        self.assertIn("{", self.run_function("service.list", [self.SERVICE_NAME]))
91
92        # Service not found
93        self.assertIn(
94            "Service not found", self.run_function("service.list", ["spongebob"])
95        )
96
97    @pytest.mark.destructive_test
98    @pytest.mark.slow_test
99    def test_enable(self):
100        """
101        Test service.enable
102        """
103        self.assertTrue(self.run_function("service.enable", [self.SERVICE_NAME]))
104
105        self.assertIn(
106            "Service not found", self.run_function("service.enable", ["spongebob"])
107        )
108
109    @pytest.mark.destructive_test
110    @pytest.mark.slow_test
111    def test_disable(self):
112        """
113        Test service.disable
114        """
115        self.assertTrue(self.run_function("service.disable", [self.SERVICE_NAME]))
116
117        self.assertIn(
118            "Service not found", self.run_function("service.disable", ["spongebob"])
119        )
120
121    @pytest.mark.destructive_test
122    @pytest.mark.slow_test
123    def test_start(self):
124        """
125        Test service.start
126        Test service.stop
127        Test service.status
128        """
129        self.assertTrue(self.run_function("service.start", [self.SERVICE_NAME]))
130
131        self.assertIn(
132            "Service not found", self.run_function("service.start", ["spongebob"])
133        )
134
135    @pytest.mark.destructive_test
136    @pytest.mark.slow_test
137    def test_stop(self):
138        """
139        Test service.stop
140        """
141        self.assertTrue(self.run_function("service.stop", [self.SERVICE_NAME]))
142
143        self.assertIn(
144            "Service not found", self.run_function("service.stop", ["spongebob"])
145        )
146
147    @pytest.mark.destructive_test
148    @pytest.mark.slow_test
149    def test_status(self):
150        """
151        Test service.status
152        """
153        # A running service
154        self.assertTrue(self.run_function("service.start", [self.SERVICE_NAME]))
155        self.assertTrue(self.run_function("service.status", [self.SERVICE_NAME]))
156
157        # A stopped service
158        self.assertTrue(self.run_function("service.stop", [self.SERVICE_NAME]))
159        self.assertFalse(self.run_function("service.status", [self.SERVICE_NAME]))
160
161        # Service not found
162        self.assertFalse(self.run_function("service.status", ["spongebob"]))
163
164    @pytest.mark.slow_test
165    def test_available(self):
166        """
167        Test service.available
168        """
169        self.assertTrue(self.run_function("service.available", [self.SERVICE_NAME]))
170        self.assertFalse(self.run_function("service.available", ["spongebob"]))
171
172    @pytest.mark.slow_test
173    def test_missing(self):
174        """
175        Test service.missing
176        """
177        self.assertFalse(self.run_function("service.missing", [self.SERVICE_NAME]))
178        self.assertTrue(self.run_function("service.missing", ["spongebob"]))
179
180    @pytest.mark.destructive_test
181    @pytest.mark.slow_test
182    def test_enabled(self):
183        """
184        Test service.enabled
185        """
186        self.assertTrue(self.run_function("service.enabled", [self.SERVICE_NAME]))
187        self.assertTrue(self.run_function("service.start", [self.SERVICE_NAME]))
188
189        self.assertTrue(self.run_function("service.enabled", [self.SERVICE_NAME]))
190        self.assertTrue(self.run_function("service.stop", [self.SERVICE_NAME]))
191
192        self.assertTrue(self.run_function("service.enabled", ["spongebob"]))
193
194    @pytest.mark.destructive_test
195    @pytest.mark.slow_test
196    def test_disabled(self):
197        """
198        Test service.disabled
199        """
200        self.assertTrue(self.run_function("service.start", [self.SERVICE_NAME]))
201        self.assertFalse(self.run_function("service.disabled", [self.SERVICE_NAME]))
202
203        self.assertTrue(self.run_function("service.disable", [self.SERVICE_NAME]))
204        self.assertTrue(self.run_function("service.disabled", [self.SERVICE_NAME]))
205        self.assertTrue(self.run_function("service.enable", [self.SERVICE_NAME]))
206        self.assertIn(
207            "Service not found", self.run_function("service.stop", ["spongebob"])
208        )
209
210    @pytest.mark.slow_test
211    def test_get_all(self):
212        """
213        Test service.get_all
214        """
215        services = self.run_function("service.get_all")
216        self.assertIsInstance(services, list)
217        self.assertIn(self.SERVICE_NAME, services)
218
219    @pytest.mark.slow_test
220    def test_get_enabled(self):
221        """
222        Test service.get_enabled
223        """
224        services = self.run_function("service.get_enabled")
225        self.assertIsInstance(services, list)
226        self.assertIn(self.SERVICE_NAME, services)
227
228    @pytest.mark.slow_test
229    def test_service_laoded(self):
230        """
231        Test service.get_enabled
232        """
233        self.assertTrue(self.run_function("service.loaded", [self.SERVICE_NAME]))
234