@@ -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 )
@@ -216,16 +218,41 @@ def test_scheduler_deadline():
216218 return 0
217219
218220 except subprocess .CalledProcessError as e :
219- output = e .output .decode ('utf-8' , errors = 'ignore' ) if e .output else ''
220- # SCHED_DEADLINE often not available
221- if "scheduler" in output .lower () or "permission" in output .lower () or "deadline" in output .lower ():
222- return (77 , "SCHED_DEADLINE not available" )
223221 logger .info ("test failed: %s" , e )
224222 return - 1
225223 except Exception as e :
226- error_str = str (e ).lower ()
227- if "deadline" in error_str or "scheduler" in error_str :
228- return (77 , "SCHED_DEADLINE not available" )
224+ logger .info ("test failed: %s" , e )
225+ return - 1
226+
227+
228+ def test_scheduler_deadline_no_period ():
229+ """Test SCHED_DEADLINE scheduler policy without period (should work - kernel allows it)."""
230+ if is_rootless ():
231+ return (77 , "SCHED_DEADLINE requires root" )
232+ if not is_sched_deadline_available ():
233+ return (77 , "SCHED_DEADLINE not available in kernel" )
234+
235+ conf = base_config ()
236+ add_all_namespaces (conf )
237+
238+ # SCHED_DEADLINE with runtime and deadline but no period
239+ # Kernel should accept this and use deadline as period
240+ conf ['process' ]['scheduler' ] = {
241+ 'policy' : 'SCHED_DEADLINE' ,
242+ 'runtime' : 10000000 , # 10ms
243+ 'deadline' : 20000000 # 20ms, no period
244+ }
245+
246+ conf ['process' ]['args' ] = ['/init' , 'true' ]
247+
248+ try :
249+ out , _ = run_and_get_output (conf , hide_stderr = True )
250+ return 0 # Should succeed
251+
252+ except subprocess .CalledProcessError as e :
253+ logger .info ("test failed: %s" , e )
254+ return - 1
255+ except Exception as e :
229256 logger .info ("test failed: %s" , e )
230257 return - 1
231258
@@ -251,12 +278,257 @@ def test_scheduler_flags():
251278 out , _ = run_and_get_output (conf , hide_stderr = True )
252279 return 0
253280
281+ except subprocess .CalledProcessError as e :
282+ logger .info ("test failed: %s" , e )
283+ return - 1
284+ except Exception as e :
285+ logger .info ("test failed: %s" , e )
286+ return - 1
287+
288+
289+ def test_scheduler_deadline_missing_runtime ():
290+ """Test SCHED_DEADLINE validation - missing runtime parameter."""
291+ if is_rootless ():
292+ return (77 , "SCHED_DEADLINE requires root" )
293+ if not is_sched_deadline_available ():
294+ return (77 , "SCHED_DEADLINE not available in kernel" )
295+
296+ conf = base_config ()
297+ add_all_namespaces (conf )
298+
299+ # Missing runtime parameter
300+ conf ['process' ]['scheduler' ] = {
301+ 'policy' : 'SCHED_DEADLINE' ,
302+ 'deadline' : 20000000 , # 20ms
303+ 'period' : 20000000 # 20ms
304+ }
305+
306+ conf ['process' ]['args' ] = ['/init' , 'true' ]
307+
308+ try :
309+ out , _ = run_and_get_output (conf , hide_stderr = False )
310+ # Should have failed due to missing runtime
311+ return - 1
312+
254313 except subprocess .CalledProcessError as e :
255314 output = e .output .decode ('utf-8' , errors = 'ignore' ) if e .output else ''
256- if "scheduler" in output .lower () or "permission" in output .lower ():
257- return (77 , "scheduler flags not available" )
315+ if "sched_setattr: `SCHED_DEADLINE` requires `runtime`" in output :
316+ return 0 # Expected validation error
317+ logger .info ("unexpected error: %s" , output )
318+ return - 1
319+ except Exception as e :
258320 logger .info ("test failed: %s" , e )
259321 return - 1
322+
323+
324+ def test_scheduler_deadline_missing_deadline ():
325+ """Test SCHED_DEADLINE validation - missing deadline parameter."""
326+ if is_rootless ():
327+ return (77 , "SCHED_DEADLINE requires root" )
328+ if not is_sched_deadline_available ():
329+ return (77 , "SCHED_DEADLINE not available in kernel" )
330+
331+ conf = base_config ()
332+ add_all_namespaces (conf )
333+
334+ # Missing deadline parameter
335+ conf ['process' ]['scheduler' ] = {
336+ 'policy' : 'SCHED_DEADLINE' ,
337+ 'runtime' : 10000000 , # 10ms
338+ 'period' : 20000000 # 20ms
339+ }
340+
341+ conf ['process' ]['args' ] = ['/init' , 'true' ]
342+
343+ try :
344+ out , _ = run_and_get_output (conf , hide_stderr = False )
345+ # Should have failed due to missing deadline
346+ return - 1
347+
348+ except subprocess .CalledProcessError as e :
349+ output = e .output .decode ('utf-8' , errors = 'ignore' ) if e .output else ''
350+ if "sched_setattr: `SCHED_DEADLINE` requires `deadline`" in output :
351+ return 0 # Expected validation error
352+ logger .info ("unexpected error: %s" , output )
353+ return - 1
354+ except Exception as e :
355+ logger .info ("test failed: %s" , e )
356+ return - 1
357+
358+
359+
360+
361+ def test_scheduler_deadline_zero_runtime ():
362+ """Test SCHED_DEADLINE validation - zero runtime."""
363+ if is_rootless ():
364+ return (77 , "SCHED_DEADLINE requires root" )
365+ if not is_sched_deadline_available ():
366+ return (77 , "SCHED_DEADLINE not available in kernel" )
367+
368+ conf = base_config ()
369+ add_all_namespaces (conf )
370+
371+ # Zero runtime
372+ conf ['process' ]['scheduler' ] = {
373+ 'policy' : 'SCHED_DEADLINE' ,
374+ 'runtime' : 0 ,
375+ 'deadline' : 20000000 , # 20ms
376+ 'period' : 20000000 # 20ms
377+ }
378+
379+ conf ['process' ]['args' ] = ['/init' , 'true' ]
380+
381+ try :
382+ out , _ = run_and_get_output (conf , hide_stderr = False )
383+ # Should have failed due to zero runtime
384+ return - 1
385+
386+ except subprocess .CalledProcessError as e :
387+ output = e .output .decode ('utf-8' , errors = 'ignore' ) if e .output else ''
388+ if "sched_setattr: `SCHED_DEADLINE` runtime must be greater than 0" in output :
389+ return 0 # Expected validation error
390+ logger .info ("unexpected error: %s" , output )
391+ return - 1
392+ except Exception as e :
393+ logger .info ("test failed: %s" , e )
394+ return - 1
395+
396+
397+ def test_scheduler_deadline_invalid_order ():
398+ """Test SCHED_DEADLINE validation - runtime > deadline."""
399+ if is_rootless ():
400+ return (77 , "SCHED_DEADLINE requires root" )
401+ if not is_sched_deadline_available ():
402+ return (77 , "SCHED_DEADLINE not available in kernel" )
403+
404+ conf = base_config ()
405+ add_all_namespaces (conf )
406+
407+ # runtime > deadline (invalid)
408+ conf ['process' ]['scheduler' ] = {
409+ 'policy' : 'SCHED_DEADLINE' ,
410+ 'runtime' : 30000000 , # 30ms
411+ 'deadline' : 20000000 , # 20ms
412+ 'period' : 40000000 # 40ms
413+ }
414+
415+ conf ['process' ]['args' ] = ['/init' , 'true' ]
416+
417+ try :
418+ out , _ = run_and_get_output (conf , hide_stderr = False )
419+ # Should have failed due to invalid order
420+ return - 1
421+
422+ except subprocess .CalledProcessError as e :
423+ output = e .output .decode ('utf-8' , errors = 'ignore' ) if e .output else ''
424+ if "sched_setattr: `SCHED_DEADLINE` runtime" in output and "must be <=" in output and "deadline" in output :
425+ return 0 # Expected validation error
426+ logger .info ("unexpected error: %s" , output )
427+ return - 1
428+ except Exception as e :
429+ logger .info ("test failed: %s" , e )
430+ return - 1
431+
432+
433+ def test_scheduler_deadline_invalid_deadline_period ():
434+ """Test SCHED_DEADLINE validation - deadline > period."""
435+ if is_rootless ():
436+ return (77 , "SCHED_DEADLINE requires root" )
437+ if not is_sched_deadline_available ():
438+ return (77 , "SCHED_DEADLINE not available in kernel" )
439+
440+ conf = base_config ()
441+ add_all_namespaces (conf )
442+
443+ # deadline > period (invalid)
444+ conf ['process' ]['scheduler' ] = {
445+ 'policy' : 'SCHED_DEADLINE' ,
446+ 'runtime' : 10000000 , # 10ms
447+ 'deadline' : 30000000 , # 30ms
448+ 'period' : 20000000 # 20ms
449+ }
450+
451+ conf ['process' ]['args' ] = ['/init' , 'true' ]
452+
453+ try :
454+ out , _ = run_and_get_output (conf , hide_stderr = False )
455+ # Should have failed due to invalid order
456+ return - 1
457+
458+ except subprocess .CalledProcessError as e :
459+ output = e .output .decode ('utf-8' , errors = 'ignore' ) if e .output else ''
460+ if "sched_setattr: `SCHED_DEADLINE` deadline" in output and "must be <=" in output and "period" in output :
461+ return 0 # Expected validation error
462+ logger .info ("unexpected error: %s" , output )
463+ return - 1
464+ except Exception as e :
465+ logger .info ("test failed: %s" , e )
466+ return - 1
467+
468+
469+ def test_scheduler_deadline_too_small_runtime ():
470+ """Test SCHED_DEADLINE validation - runtime < min."""
471+ if is_rootless ():
472+ return (77 , "SCHED_DEADLINE requires root" )
473+ if not is_sched_deadline_available ():
474+ return (77 , "SCHED_DEADLINE not available in kernel" )
475+
476+ conf = base_config ()
477+ add_all_namespaces (conf )
478+
479+ conf ['process' ]['scheduler' ] = {
480+ 'policy' : 'SCHED_DEADLINE' ,
481+ 'runtime' : 1023 , # too small
482+ 'deadline' : 10000000 , # 10ms
483+ }
484+
485+ conf ['process' ]['args' ] = ['/init' , 'true' ]
486+
487+ try :
488+ out , _ = run_and_get_output (conf , hide_stderr = False )
489+ # Should have failed due to too small runtime.
490+ return - 1
491+
492+ except subprocess .CalledProcessError as e :
493+ output = e .output .decode ('utf-8' , errors = 'ignore' ) if e .output else ''
494+ if "sched_setattr: `SCHED_DEADLINE` runtime " in output and " must be between " in output :
495+ return 0 # Expected validation error
496+ logger .info ("unexpected error: %s" , output )
497+ return - 1
498+ except Exception as e :
499+ logger .info ("test failed: %s" , e )
500+ return - 1
501+
502+
503+ def test_scheduler_deadline_too_big_runtime ():
504+ """Test SCHED_DEADLINE validation - runtime > max."""
505+ if is_rootless ():
506+ return (77 , "SCHED_DEADLINE requires root" )
507+ if not is_sched_deadline_available ():
508+ return (77 , "SCHED_DEADLINE not available in kernel" )
509+
510+ conf = base_config ()
511+ add_all_namespaces (conf )
512+
513+ conf ['process' ]['scheduler' ] = {
514+ 'policy' : 'SCHED_DEADLINE' ,
515+ 'runtime' : 9223372036854775809 ,
516+ 'deadline' : 9223372036854775810 ,
517+ }
518+
519+ conf ['process' ]['args' ] = ['/init' , 'true' ]
520+
521+ try :
522+ out , _ = run_and_get_output (conf , hide_stderr = False )
523+ # Should have failed due to too big runtime.
524+ return - 1
525+
526+ except subprocess .CalledProcessError as e :
527+ output = e .output .decode ('utf-8' , errors = 'ignore' ) if e .output else ''
528+ if "sched_setattr: `SCHED_DEADLINE` runtime " in output and " must be between " in output :
529+ return 0 # Expected validation error
530+ logger .info ("unexpected error: %s" , output )
531+ return - 1
260532 except Exception as e :
261533 logger .info ("test failed: %s" , e )
262534 return - 1
@@ -270,7 +542,15 @@ def test_scheduler_flags():
270542 "scheduler-other" : test_scheduler_other ,
271543 "scheduler-nice-value" : test_scheduler_nice_value ,
272544 "scheduler-deadline" : test_scheduler_deadline ,
545+ "scheduler-deadline-no-period" : test_scheduler_deadline_no_period ,
273546 "scheduler-flags" : test_scheduler_flags ,
547+ "scheduler-deadline-missing-runtime" : test_scheduler_deadline_missing_runtime ,
548+ "scheduler-deadline-missing-deadline" : test_scheduler_deadline_missing_deadline ,
549+ "scheduler-deadline-zero-runtime" : test_scheduler_deadline_zero_runtime ,
550+ "scheduler-deadline-invalid-order" : test_scheduler_deadline_invalid_order ,
551+ "scheduler-deadline-invalid-deadline-period" : test_scheduler_deadline_invalid_deadline_period ,
552+ "scheduler-deadline-too-small-runtime" : test_scheduler_deadline_too_small_runtime ,
553+ "scheduler-deadline-too-big-runtime" : test_scheduler_deadline_too_big_runtime ,
274554}
275555
276556if __name__ == "__main__" :
0 commit comments