@@ -194,9 +194,11 @@ def test_scheduler_nice_value():
194194
195195
196196def test_scheduler_deadline ():
197- """Test SCHED_DEADLINE scheduler policy."""
197+ """Test SCHED_DEADLINE scheduler policy with all parameters (working case) ."""
198198 if is_rootless ():
199199 return (77 , "SCHED_DEADLINE requires root" )
200+ if not is_sched_deadline_available ():
201+ return (77 , "SCHED_DEADLINE not available in kernel" )
200202
201203 conf = base_config ()
202204 add_all_namespaces (conf )
@@ -230,6 +232,44 @@ def test_scheduler_deadline():
230232 return - 1
231233
232234
235+ def test_scheduler_deadline_no_period ():
236+ """Test SCHED_DEADLINE scheduler policy without period (should work - kernel allows it)."""
237+ if is_rootless ():
238+ return (77 , "SCHED_DEADLINE requires root" )
239+ if not is_sched_deadline_available ():
240+ return (77 , "SCHED_DEADLINE not available in kernel" )
241+
242+ conf = base_config ()
243+ add_all_namespaces (conf )
244+
245+ # SCHED_DEADLINE with runtime and deadline but no period
246+ # Kernel should accept this and use deadline as period
247+ conf ['process' ]['scheduler' ] = {
248+ 'policy' : 'SCHED_DEADLINE' ,
249+ 'runtime' : 10000000 , # 10ms
250+ 'deadline' : 20000000 # 20ms, no period
251+ }
252+
253+ conf ['process' ]['args' ] = ['/init' , 'true' ]
254+
255+ try :
256+ out , _ = run_and_get_output (conf , hide_stderr = True )
257+ return 0 # Should succeed
258+
259+ except subprocess .CalledProcessError as e :
260+ output = e .output .decode ('utf-8' , errors = 'ignore' ) if e .output else ''
261+ if "scheduler" in output .lower () or "permission" in output .lower () or "deadline" in output .lower ():
262+ return (77 , "SCHED_DEADLINE not available" )
263+ logger .info ("test failed: %s" , e )
264+ return - 1
265+ except Exception as e :
266+ error_str = str (e ).lower ()
267+ if "deadline" in error_str or "scheduler" in error_str :
268+ return (77 , "SCHED_DEADLINE not available" )
269+ logger .info ("test failed: %s" , e )
270+ return - 1
271+
272+
233273def test_scheduler_flags ():
234274 """Test scheduler with flags (reset_on_fork)."""
235275 if is_rootless ():
@@ -262,6 +302,198 @@ def test_scheduler_flags():
262302 return - 1
263303
264304
305+ def test_scheduler_deadline_missing_runtime ():
306+ """Test SCHED_DEADLINE validation - missing runtime parameter."""
307+ if is_rootless ():
308+ return (77 , "SCHED_DEADLINE requires root" )
309+ if not is_sched_deadline_available ():
310+ return (77 , "SCHED_DEADLINE not available in kernel" )
311+
312+ conf = base_config ()
313+ add_all_namespaces (conf )
314+
315+ # Missing runtime parameter
316+ conf ['process' ]['scheduler' ] = {
317+ 'policy' : 'SCHED_DEADLINE' ,
318+ 'deadline' : 20000000 , # 20ms
319+ 'period' : 20000000 # 20ms
320+ }
321+
322+ conf ['process' ]['args' ] = ['/init' , 'true' ]
323+
324+ try :
325+ out , _ = run_and_get_output (conf , hide_stderr = False )
326+ # Should have failed due to missing runtime
327+ return - 1
328+
329+ except subprocess .CalledProcessError as e :
330+ output = e .output .decode ('utf-8' , errors = 'ignore' ) if e .output else ''
331+ if "sched_setattr: `SCHED_DEADLINE` requires `runtime`" in output :
332+ return 0 # Expected validation error
333+ if "scheduler" in output .lower () or "deadline" in output .lower ():
334+ return (77 , "SCHED_DEADLINE not available" )
335+ logger .info ("unexpected error: %s" , output )
336+ return - 1
337+ except Exception as e :
338+ logger .info ("test failed: %s" , e )
339+ return - 1
340+
341+
342+ def test_scheduler_deadline_missing_deadline ():
343+ """Test SCHED_DEADLINE validation - missing deadline parameter."""
344+ if is_rootless ():
345+ return (77 , "SCHED_DEADLINE requires root" )
346+ if not is_sched_deadline_available ():
347+ return (77 , "SCHED_DEADLINE not available in kernel" )
348+
349+ conf = base_config ()
350+ add_all_namespaces (conf )
351+
352+ # Missing deadline parameter
353+ conf ['process' ]['scheduler' ] = {
354+ 'policy' : 'SCHED_DEADLINE' ,
355+ 'runtime' : 10000000 , # 10ms
356+ 'period' : 20000000 # 20ms
357+ }
358+
359+ conf ['process' ]['args' ] = ['/init' , 'true' ]
360+
361+ try :
362+ out , _ = run_and_get_output (conf , hide_stderr = False )
363+ # Should have failed due to missing deadline
364+ return - 1
365+
366+ except subprocess .CalledProcessError as e :
367+ output = e .output .decode ('utf-8' , errors = 'ignore' ) if e .output else ''
368+ if "sched_setattr: `SCHED_DEADLINE` requires `deadline`" in output :
369+ return 0 # Expected validation error
370+ if "scheduler" in output .lower () or "deadline" in output .lower ():
371+ return (77 , "SCHED_DEADLINE not available" )
372+ logger .info ("unexpected error: %s" , output )
373+ return - 1
374+ except Exception as e :
375+ logger .info ("test failed: %s" , e )
376+ return - 1
377+
378+
379+
380+
381+ def test_scheduler_deadline_zero_runtime ():
382+ """Test SCHED_DEADLINE validation - zero runtime."""
383+ if is_rootless ():
384+ return (77 , "SCHED_DEADLINE requires root" )
385+ if not is_sched_deadline_available ():
386+ return (77 , "SCHED_DEADLINE not available in kernel" )
387+
388+ conf = base_config ()
389+ add_all_namespaces (conf )
390+
391+ # Zero runtime
392+ conf ['process' ]['scheduler' ] = {
393+ 'policy' : 'SCHED_DEADLINE' ,
394+ 'runtime' : 0 ,
395+ 'deadline' : 20000000 , # 20ms
396+ 'period' : 20000000 # 20ms
397+ }
398+
399+ conf ['process' ]['args' ] = ['/init' , 'true' ]
400+
401+ try :
402+ out , _ = run_and_get_output (conf , hide_stderr = False )
403+ # Should have failed due to zero runtime
404+ return - 1
405+
406+ except subprocess .CalledProcessError as e :
407+ output = e .output .decode ('utf-8' , errors = 'ignore' ) if e .output else ''
408+ if "sched_setattr: `SCHED_DEADLINE` runtime must be greater than 0" in output :
409+ return 0 # Expected validation error
410+ if "scheduler" in output .lower () or "deadline" in output .lower ():
411+ return (77 , "SCHED_DEADLINE not available" )
412+ logger .info ("unexpected error: %s" , output )
413+ return - 1
414+ except Exception as e :
415+ logger .info ("test failed: %s" , e )
416+ return - 1
417+
418+
419+ def test_scheduler_deadline_invalid_order ():
420+ """Test SCHED_DEADLINE validation - runtime > deadline."""
421+ if is_rootless ():
422+ return (77 , "SCHED_DEADLINE requires root" )
423+ if not is_sched_deadline_available ():
424+ return (77 , "SCHED_DEADLINE not available in kernel" )
425+
426+ conf = base_config ()
427+ add_all_namespaces (conf )
428+
429+ # runtime > deadline (invalid)
430+ conf ['process' ]['scheduler' ] = {
431+ 'policy' : 'SCHED_DEADLINE' ,
432+ 'runtime' : 30000000 , # 30ms
433+ 'deadline' : 20000000 , # 20ms
434+ 'period' : 40000000 # 40ms
435+ }
436+
437+ conf ['process' ]['args' ] = ['/init' , 'true' ]
438+
439+ try :
440+ out , _ = run_and_get_output (conf , hide_stderr = False )
441+ # Should have failed due to invalid order
442+ return - 1
443+
444+ except subprocess .CalledProcessError as e :
445+ output = e .output .decode ('utf-8' , errors = 'ignore' ) if e .output else ''
446+ if "sched_setattr: `SCHED_DEADLINE` runtime" in output and "must be <=" in output and "deadline" in output :
447+ return 0 # Expected validation error
448+ if "scheduler" in output .lower () or "deadline" in output .lower ():
449+ return (77 , "SCHED_DEADLINE not available" )
450+ logger .info ("unexpected error: %s" , output )
451+ return - 1
452+ except Exception as e :
453+ logger .info ("test failed: %s" , e )
454+ return - 1
455+
456+
457+ def test_scheduler_deadline_invalid_deadline_period ():
458+ """Test SCHED_DEADLINE validation - deadline > period."""
459+ if is_rootless ():
460+ return (77 , "SCHED_DEADLINE requires root" )
461+ if not is_sched_deadline_available ():
462+ return (77 , "SCHED_DEADLINE not available in kernel" )
463+
464+ conf = base_config ()
465+ add_all_namespaces (conf )
466+
467+ # deadline > period (invalid)
468+ conf ['process' ]['scheduler' ] = {
469+ 'policy' : 'SCHED_DEADLINE' ,
470+ 'runtime' : 10000000 , # 10ms
471+ 'deadline' : 30000000 , # 30ms
472+ 'period' : 20000000 # 20ms
473+ }
474+
475+ conf ['process' ]['args' ] = ['/init' , 'true' ]
476+
477+ try :
478+ out , _ = run_and_get_output (conf , hide_stderr = False )
479+ # Should have failed due to invalid order
480+ return - 1
481+
482+ except subprocess .CalledProcessError as e :
483+ output = e .output .decode ('utf-8' , errors = 'ignore' ) if e .output else ''
484+ if "sched_setattr: `SCHED_DEADLINE` deadline" in output and "must be <=" in output and "period" in output :
485+ return 0 # Expected validation error
486+ if "scheduler" in output .lower () or "deadline" in output .lower ():
487+ return (77 , "SCHED_DEADLINE not available" )
488+ logger .info ("unexpected error: %s" , output )
489+ return - 1
490+ except Exception as e :
491+ logger .info ("test failed: %s" , e )
492+ return - 1
493+
494+
495+
496+
265497all_tests = {
266498 "scheduler-fifo" : test_scheduler_fifo ,
267499 "scheduler-rr" : test_scheduler_rr ,
@@ -270,7 +502,13 @@ def test_scheduler_flags():
270502 "scheduler-other" : test_scheduler_other ,
271503 "scheduler-nice-value" : test_scheduler_nice_value ,
272504 "scheduler-deadline" : test_scheduler_deadline ,
505+ "scheduler-deadline-no-period" : test_scheduler_deadline_no_period ,
273506 "scheduler-flags" : test_scheduler_flags ,
507+ "scheduler-deadline-missing-runtime" : test_scheduler_deadline_missing_runtime ,
508+ "scheduler-deadline-missing-deadline" : test_scheduler_deadline_missing_deadline ,
509+ "scheduler-deadline-zero-runtime" : test_scheduler_deadline_zero_runtime ,
510+ "scheduler-deadline-invalid-order" : test_scheduler_deadline_invalid_order ,
511+ "scheduler-deadline-invalid-deadline-period" : test_scheduler_deadline_invalid_deadline_period ,
274512}
275513
276514if __name__ == "__main__" :
0 commit comments