11from ansible_collections .nextcloud .admin .plugins .module_utils .nc_tools import (
22 convert_string ,
3+ execute_occ_command ,
34 run_occ ,
45)
56import ansible_collections .nextcloud .admin .plugins .module_utils .exceptions as occ_exceptions
@@ -50,6 +51,82 @@ def test_backslash_behaviour(self):
5051 )
5152
5253
54+ class TestExecuteOccCommand (unittest .TestCase ):
55+ def setUp (self ):
56+ self .mock_conn = MagicMock ()
57+ self .module = MagicMock ()
58+ self .mock_stat = patch ("os.stat" ).start ()
59+ self .mock_getuid = patch ("os.getuid" ).start ()
60+ self .mock_getgid = patch ("os.getgid" ).start ()
61+ self .mock_setuid = patch ("os.setuid" ).start ()
62+ self .mock_setgid = patch ("os.setgid" ).start ()
63+ self .mock_stat .return_value .st_uid = 1234
64+ self .mock_stat .return_value .st_gid = 1234
65+ self .mock_getuid .return_value = 1234
66+ self .mock_getgid .return_value = 1234
67+ self .addCleanup (patch .stopall )
68+ self .module .run_command .return_value = (0 , "output" , "" )
69+
70+ def test_execute_occ_command_success (self ):
71+ execute_occ_command (
72+ self .mock_conn , self .module , "/path/to/php" , ["/path/to/occ" , "command" ]
73+ )
74+
75+ self .mock_conn .send .assert_called_once_with (
76+ {"rc" : 0 , "stdout" : "output" , "stderr" : "" }
77+ )
78+
79+ def test_change_uid_execute_occ_command_success (self ):
80+ self .mock_getuid .return_value = 0
81+ self .mock_getgid .return_value = 0
82+
83+ execute_occ_command (
84+ self .mock_conn , self .module , "/path/to/php" , ["/path/to/occ" , "command" ]
85+ )
86+
87+ self .mock_conn .send .assert_called_once_with (
88+ {"rc" : 0 , "stdout" : "output" , "stderr" : "" }
89+ )
90+ self .mock_setuid .assert_called_with (1234 )
91+ self .mock_setgid .assert_called_with (1234 )
92+
93+ def test_occ_command_FileNotFoundError (self ):
94+ self .mock_stat .side_effect = FileNotFoundError
95+
96+ execute_occ_command (
97+ self .mock_conn , self .module , "/path/to/php" , ["/path/to/occ" , "command" ]
98+ )
99+
100+ self .mock_conn .send .assert_called_once_with (
101+ {"exception" : "OccFileNotFoundException" }
102+ )
103+
104+ def test_occ_command_PermissionError (self ):
105+ self .mock_getuid .return_value = 0
106+ self .mock_getgid .return_value = 0
107+ self .mock_setuid .side_effect = PermissionError
108+
109+ execute_occ_command (
110+ self .mock_conn , self .module , "/path/to/php" , ["/path/to/occ" , "command" ]
111+ )
112+
113+ self .mock_conn .send .assert_called_once_with (
114+ {
115+ "exception" : "OccAuthenticationException" ,
116+ "msg" : "Insufficient permissions to switch to user id 1234." ,
117+ }
118+ )
119+
120+ def test_occ_command_AnyError (self ):
121+ self .mock_getuid .side_effect = Exception ("TKIAL" )
122+
123+ execute_occ_command (
124+ self .mock_conn , self .module , "/path/to/php" , ["/path/to/occ" , "command" ]
125+ )
126+
127+ self .mock_conn .send .assert_called_once_with ({"exception" : "TKIAL" })
128+
129+
53130class TestRunOcc (unittest .TestCase ):
54131
55132 def setUp (self ):
@@ -60,16 +137,29 @@ def setUp(self):
60137 "php_runtime" : "/usr/bin/php" ,
61138 }
62139
63- @patch ("os.stat" )
64- @patch ("os.getuid" )
65- @patch ("os.setgid" )
66- @patch ("os.setuid" )
67- def test_run_occ_success (self , mock_setuid , mock_setgid , mock_getuid , mock_stat ):
68- # Setup mocks
69- mock_stat .return_value .st_uid = 1000
70- mock_stat .return_value .st_gid = 1000
71- mock_getuid .return_value = 1001
72- self .module .run_command .return_value = (0 , "Success" , "" )
140+ self .mock_process = patch (
141+ "ansible_collections.nextcloud.admin.plugins.module_utils.nc_tools.Process"
142+ ).start ()
143+ self .mock_instance = self .mock_process .return_value
144+ self .mock_instance .start .return_value = None
145+ self .mock_instance .join .return_value = None
146+
147+ self .mock_pipe_parent , self .mock_pipe_child = MagicMock (), MagicMock ()
148+ patcher_pipe = patch (
149+ "ansible_collections.nextcloud.admin.plugins.module_utils.nc_tools.Pipe" ,
150+ return_value = (self .mock_pipe_parent , self .mock_pipe_child ),
151+ )
152+ patcher_pipe .start ()
153+
154+ self .mock_pipe_parent .recv .return_value = {
155+ "rc" : 0 ,
156+ "stdout" : "Success" ,
157+ "stderr" : "" ,
158+ }
159+
160+ self .addCleanup (patch .stopall )
161+
162+ def test_run_occ_success (self ):
73163
74164 # Call the function
75165 returnCode , stdOut , stdErr , maintenanceMode = run_occ (self .module , "status" )
@@ -79,21 +169,14 @@ def test_run_occ_success(self, mock_setuid, mock_setgid, mock_getuid, mock_stat)
79169 self .assertEqual (stdOut , "Success" )
80170 self .assertEqual (stdErr , "" )
81171 self .assertFalse (maintenanceMode )
82- mock_setgid .assert_called_once_with (1000 )
83- mock_setuid .assert_called_once_with (1000 )
84172
85- @patch ("os.stat" )
86- @patch ("os.getuid" )
87- def test_run_occ_maintenance_mode (self , mock_getuid , mock_stat ):
173+ def test_run_occ_maintenance_mode (self ):
88174 # Setup mocks
89- mock_stat .return_value .st_uid = 1000
90- mock_stat .return_value .st_gid = 1000
91- mock_getuid .return_value = 1000
92- self .module .run_command .return_value = (
93- 0 ,
94- "" ,
95- "Nextcloud is in maintenance mode, no apps are loaded." ,
96- )
175+ self .mock_pipe_parent .recv .return_value = {
176+ "rc" : 0 ,
177+ "stdout" : "" ,
178+ "stderr" : "Nextcloud is in maintenance mode, no apps are loaded." ,
179+ }
97180
98181 # Call the function
99182 returnCode , stdOut , stdErr , maintenanceMode = run_occ (self .module , "status" )
@@ -107,117 +190,69 @@ def test_run_occ_maintenance_mode(self, mock_getuid, mock_stat):
107190 self .assertIn ("maintenance mode" , stdErr )
108191 self .assertTrue (maintenanceMode )
109192
110- @patch ("os.stat" )
111- @patch ("os.getuid" , return_value = 1000 )
112- def test_file_not_found_exception (self , mock_getuid , mock_stat ):
193+ def test_file_not_found_exception (self ):
113194 # Simulate FileNotFoundError when accessing the occ file
114- mock_stat .side_effect = FileNotFoundError
195+ self .mock_pipe_parent .recv .return_value = {
196+ "exception" : "OccFileNotFoundException" ,
197+ "msg" : "" ,
198+ }
115199
116200 with self .assertRaises (occ_exceptions .OccFileNotFoundException ):
117201 run_occ (self .module , "status" )
118202
119- @patch ("os.stat" )
120- @patch ("os.setuid" )
121- @patch ("os.setgid" )
122- @patch ("os.getuid" , return_value = 1000 )
123- def test_authentication_exception (
124- self , mock_getuid , mock_setgid , mock_setuid , mock_stat
125- ):
203+ def test_authentication_exception (self ):
126204 # Simulate PermissionError when trying to change user
127- mock_stat .return_value .st_uid = 2000
128- mock_stat .return_value .st_gid = 2000
129- mock_setuid .side_effect = PermissionError
205+ self .mock_pipe_parent .recv .return_value = {
206+ "exception" : "OccAuthenticationException" ,
207+ "msg" : "" ,
208+ }
130209
131210 with self .assertRaises (occ_exceptions .OccAuthenticationException ):
132211 run_occ (self .module , "status" )
133212
134- @patch ("os.stat" )
135- @patch ("os.setuid" )
136- @patch ("os.setgid" )
137- @patch ("os.getuid" , return_value = 1000 )
138- def test_no_commands_defined_exception (
139- self , mock_getuid , mock_setgid , mock_setuid , mock_stat
140- ):
141- # Mock successful stat call and simulate command execution error
142- mock_stat .return_value .st_uid = 1000
143- mock_stat .return_value .st_gid = 1000
144- self .module .run_command .return_value = (1 , "" , "Command 'foo' is not defined." )
213+ def test_no_commands_defined_exception (self ):
214+ # simulate command execution error
215+ self .mock_pipe_parent .recv .return_value = {
216+ "rc" : 1 ,
217+ "stdout" : "" ,
218+ "stderr" : "Command 'foo' is not defined." ,
219+ }
145220
146221 with self .assertRaises (occ_exceptions .OccNoCommandsDefined ):
147222 run_occ (self .module , "foo" )
148223
149- @patch ("os.stat" )
150- @patch ("os.setuid" )
151- @patch ("os.setgid" )
152- @patch ("os.getuid" , return_value = 1000 )
153- def test_not_enough_arguments_exception (
154- self , mock_getuid , mock_setgid , mock_setuid , mock_stat
155- ):
156- # Mock successful stat call and simulate command execution error
157- mock_stat .return_value .st_uid = 1000
158- mock_stat .return_value .st_gid = 1000
159- self .module .run_command .return_value = (
160- 1 ,
161- "" ,
162- 'Not enough arguments (missing: "bar").' ,
163- )
164-
224+ def test_not_enough_arguments_exception (self ):
225+ # simulate command execution error
226+ self .mock_pipe_parent .recv .return_value = {
227+ "rc" : 1 ,
228+ "stdout" : "" ,
229+ "stderr" : 'Not enough arguments (missing: "bar").' ,
230+ }
165231 with self .assertRaises (occ_exceptions .OccNotEnoughArguments ):
166232 run_occ (self .module , "foo" )
167233
168- @patch ("os.stat" )
169- @patch ("os.setuid" )
170- @patch ("os.setgid" )
171- @patch ("os.getuid" , return_value = 1000 )
172- def test_option_not_defined_exception (
173- self , mock_getuid , mock_setgid , mock_setuid , mock_stat
174- ):
175- # Mock successful stat call and simulate command execution error
176- mock_stat .return_value .st_uid = 1000
177- mock_stat .return_value .st_gid = 1000
178- self .module .run_command .return_value = (
179- 1 ,
180- "" ,
181- "The option '--baz' does not exist." ,
182- )
234+ def test_option_not_defined_exception (self ):
235+ self .mock_pipe_parent .recv .return_value = {
236+ "rc" : 1 ,
237+ "stdout" : "" ,
238+ "stderr" : "The option '--baz' does not exist." ,
239+ }
183240
184241 with self .assertRaises (occ_exceptions .OccOptionNotDefined ):
185242 run_occ (self .module , "foo --baz" )
186243
187- @patch ("os.stat" )
188- @patch ("os.setuid" )
189- @patch ("os.setgid" )
190- @patch ("os.getuid" , return_value = 1000 )
191- def test_option_requires_value_exception (
192- self , mock_getuid , mock_setgid , mock_setuid , mock_stat
193- ):
194- # Mock successful stat call and simulate command execution error
195- mock_stat .return_value .st_uid = 1000
196- mock_stat .return_value .st_gid = 1000
197- self .module .run_command .return_value = (
198- 1 ,
199- "" ,
200- "The option '--baz' requires a value." ,
201- )
244+ def test_option_requires_value_exception (self ):
245+ self .mock_pipe_parent .recv .return_value = {
246+ "rc" : 1 ,
247+ "stdout" : "" ,
248+ "stderr" : "The option '--baz' requires a value." ,
249+ }
202250
203251 with self .assertRaises (occ_exceptions .OccOptionRequiresValue ):
204252 run_occ (self .module , "foo --baz" )
205253
206- @patch ("os.stat" )
207- @patch ("os.setuid" )
208- @patch ("os.setgid" )
209- @patch ("os.getuid" , return_value = 1000 )
210- def test_empty_msg_exception (
211- self , mock_getuid , mock_setgid , mock_setuid , mock_stat
212- ):
213- # Mock successful stat call and simulate command execution error
214- mock_stat .return_value .st_uid = 1000
215- mock_stat .return_value .st_gid = 1000
216- self .module .run_command .return_value = (
217- 1 ,
218- "" ,
219- "" ,
220- )
254+ def test_empty_msg_exception (self ):
255+ self .mock_pipe_parent .recv .return_value = {"rc" : 1 , "stdout" : "" , "stderr" : "" }
221256
222257 with self .assertRaises (occ_exceptions .OccExceptions ):
223258 run_occ (self .module , "foo --baz" )
0 commit comments