77from sio3pack .packages .package .configuration import SIO3PackConfig
88from sio3pack .workflow import ExecutionTask , ScriptTask , Workflow
99from sio3pack .workflow .execution import ObjectReadStream , ObjectWriteStream
10+ from sio3pack .workflow .execution .filesystems import ObjectFilesystem
1011from tests .fixtures import PackageInfo , get_package
1112from tests .packages .sinolpack .utils import common_checks
1213
@@ -25,9 +26,10 @@ def test_unpack_workflows(get_package):
2526
2627 if package_info .task_id == "abc" :
2728 # We expect 2 workflows: compile checker and outgen
28- assert len (workflows ) == 2
29+ assert len (workflows ) == 3
2930 assert workflows [0 ].name == "Compile checker"
30- assert workflows [1 ].name == "Outgen tests"
31+ assert workflows [1 ].name == "Run ingen"
32+ assert workflows [2 ].name == "Outgen tests"
3133 elif package_info .task_id == "wer" :
3234 # We expect 3 workflows: compile checker, outgen and inwer
3335 assert len (workflows ) == 3
@@ -166,3 +168,141 @@ def test_custom_workflow(get_package):
166168
167169 assert num_custom == 3 , "Should have 3 custom execution tasks"
168170 assert num_custom_scripts == 3 , "Should have 3 custom script tasks"
171+
172+
173+ @pytest .mark .parametrize ("get_package" , ["simple" ], indirect = True )
174+ def test_user_out_workflow (get_package ):
175+ package_info : PackageInfo = get_package ()
176+ package = sio3pack .from_file (package_info .path , SIO3PackConfig .detect ())
177+ common_checks (package_info , package )
178+
179+ program = LocalFile (os .path .join (package .rootdir , "prog" , "abc.cpp" ))
180+ test = package .tests [0 ]
181+
182+ op = package .get_user_out_operation (program , test )
183+ workflows = [wf for wf in op .get_workflow ()]
184+ assert len (workflows ) == 1
185+ workflow = workflows [0 ]
186+
187+ assert len (workflow .observable_objects ) == 1 , "Should have just user out object"
188+ assert workflow .observable_objects [0 ].handle .startswith ("user_out_" ), "User out object should be user_out_"
189+
190+ num_compiles = 0
191+ num_runs = 0
192+ for task in workflow .tasks :
193+ if task .name == f"Compile { program .path } using g++-12.2" :
194+ assert len (task .processes ) == 1 , "Compile task should have one process"
195+ assert task .processes [0 ].image == "compiler:g++-12.2" , "Compile task should use g++-12.2 image"
196+ num_compiles += 1
197+ elif task .name .startswith ("Run solution for test" ):
198+ num_runs += 1
199+ assert len (task .processes ) == 1 , "Run task should have one process"
200+ proc = task .processes [0 ]
201+ stdin_fd = proc .descriptor_manager .get (0 )
202+ assert isinstance (stdin_fd , ObjectReadStream ), "Run task should have stdin stream"
203+ stdout_fd = proc .descriptor_manager .get (1 )
204+ assert isinstance (stdout_fd , ObjectWriteStream ), "Run task should have stdout stream"
205+ assert stdout_fd .object .handle .startswith ("user_out" ), "Run task should have user_out stream"
206+
207+ assert num_compiles == 1 , "Should have one compile task"
208+ assert num_runs == 1 , "Should have one run task"
209+
210+
211+ @pytest .mark .parametrize ("get_package" , ["simple" ], indirect = True )
212+ def test_test_run_workflow (get_package ):
213+ package_info : PackageInfo = get_package ()
214+ package = sio3pack .from_file (package_info .path , SIO3PackConfig .detect ())
215+ common_checks (package_info , package )
216+
217+ program = LocalFile (os .path .join (package .rootdir , "prog" , "abc.cpp" ))
218+ test = LocalFile (os .path .join (package .rootdir , "in" , "abc0.in" ))
219+
220+ op = package .get_test_run_operation (program , test )
221+ workflows = [wf for wf in op .get_workflow ()]
222+ assert len (workflows ) == 1
223+ workflow = workflows [0 ]
224+
225+ assert len (workflow .observable_objects ) == 1 , "Should have just user out object"
226+ out_obj = workflow .observable_objects [0 ]
227+ assert out_obj .handle == f"test_run_{ program .filename } " , "User out object should be user_out_<filename>"
228+
229+ assert len (workflow .tasks ) == 2 , "Should have two tasks"
230+ assert workflow .tasks [0 ].name == f"Compile { program .path } using g++-12.2" , "First task should be compile"
231+ assert workflow .tasks [1 ].name == f"Run solution for test" , "Second task should be run"
232+ exec_task = workflow .tasks [1 ]
233+ assert isinstance (exec_task , ExecutionTask ), "Second task should be an execution task"
234+ assert len (exec_task .processes ) == 1 , "Run task should have one process"
235+ proc = exec_task .processes [0 ]
236+ stdin_fd = proc .descriptor_manager .get (0 )
237+ assert isinstance (stdin_fd , ObjectReadStream ), "Run task should have stdin stream"
238+ assert stdin_fd .object .handle == test .path , "Run task should have stdin stream"
239+ stdout_fd = proc .descriptor_manager .get (1 )
240+ assert isinstance (stdout_fd , ObjectWriteStream ), "Run task should have stdout stream"
241+ assert stdout_fd .object .handle == out_obj .handle , "Run task should have stdout stream"
242+
243+
244+ @pytest .mark .parametrize ("get_package" , ["extra_files" ], indirect = True )
245+ def test_extra_files (get_package ):
246+ package_info : PackageInfo = get_package ()
247+ package = sio3pack .from_file (package_info .path , SIO3PackConfig .detect ())
248+ common_checks (package_info , package )
249+
250+ program = LocalFile (os .path .join (package .rootdir , "prog" , "ext.cpp" ))
251+
252+ op = package .get_run_operation (program )
253+ workflows = [wf for wf in op .get_workflow ()]
254+ assert len (workflows ) == 1
255+ workflow = workflows [0 ]
256+
257+ assert len (workflow .external_objects ) == 5
258+ extlib_h = None
259+ extlib_py = None
260+ for obj in workflow .external_objects :
261+ if obj .handle .endswith ("extlib.h" ):
262+ extlib_h = obj
263+ elif obj .handle .endswith ("extlib.py" ):
264+ extlib_py = obj
265+ assert extlib_h is not None , "Should have extlib.h as external object"
266+ assert extlib_py is not None , "Should have extlib.py as external object"
267+
268+ for task in workflow .tasks :
269+ if isinstance (task , ExecutionTask ):
270+ if task .name == f"Compile { program .path } using g++-12.2" :
271+ assert task .filesystem_manager .len () == 2
272+ ext_fs = task .filesystem_manager .get_by_id (1 )
273+ assert isinstance (ext_fs , ObjectFilesystem ), "Should have object filesystem with external file"
274+ assert ext_fs .object .handle == extlib_h .handle , "Should have extlib.h as external file"
275+
276+ assert task .mountnamespace_manager .len () == 1 , "Should have one mount namespace"
277+ assert len (task .mountnamespace_manager .get_by_id (0 ).mountpoints ) == 2 , "Should have two mount points"
278+
279+ proc = task .processes [0 ]
280+ assert "extlib.h" in proc .arguments , "Should have extlib.h in arguments"
281+ elif task .name .startswith ("Run solution for test" ):
282+ assert task .filesystem_manager .len () == 2
283+ ext_fs = task .filesystem_manager .get_by_id (1 )
284+ assert isinstance (ext_fs , ObjectFilesystem ), "Should have object filesystem with external file"
285+ assert ext_fs .object .handle == extlib_py .handle , "Should have extlib.py as external file"
286+
287+ assert task .mountnamespace_manager .len () == 1 , "Should have one mount namespace"
288+ assert len (task .mountnamespace_manager .get_by_id (0 ).mountpoints ) == 2 , "Should have two mount points"
289+
290+ # Check that python compilation doesnt have extlib.h in compilation args.
291+ program = LocalFile (os .path .join (package .rootdir , "prog" , "ext.py" ))
292+ op = package .get_run_operation (program )
293+ workflows = [wf for wf in op .get_workflow ()]
294+ assert len (workflows ) == 1
295+
296+ for task in workflows [0 ].tasks :
297+ if isinstance (task , ExecutionTask ):
298+ if task .name == f"Compile { program .path } using python" :
299+ assert task .filesystem_manager .len () == 2
300+ ext_fs = task .filesystem_manager .get_by_id (1 )
301+ assert isinstance (ext_fs , ObjectFilesystem ), "Should have object filesystem with external file"
302+ assert ext_fs .object .handle == extlib_py .handle , "Should have extlib.py as external file"
303+
304+ assert task .mountnamespace_manager .len () == 1 , "Should have one mount namespace"
305+ assert len (task .mountnamespace_manager .get_by_id (0 ).mountpoints ) == 2 , "Should have two mount points"
306+
307+ proc = task .processes [0 ]
308+ assert "extlib.h" not in proc .arguments , "Should not have extlib.h in arguments"
0 commit comments