@@ -212,6 +212,18 @@ impl Strategy {
212212 for ( _idx, min, max_opt) in & flexible_requests {
213213 remaining_flexible -= 1 ;
214214
215+ // First verify we have enough space for minimum requirement
216+ if * min > remaining {
217+ // Clean up any changes we made since we can't complete all requests
218+ while planner. has_changes ( ) {
219+ planner. undo ( ) ;
220+ }
221+ return Err ( PlanError :: RegionOutOfBounds {
222+ start : current,
223+ end : current + min,
224+ } ) ;
225+ }
226+
215227 let size = if remaining_flexible == 0 {
216228 // Last flexible partition gets all remaining space
217229 let size = remaining;
@@ -231,9 +243,19 @@ impl Strategy {
231243 }
232244 } ;
233245
234- planner. plan_add_partition ( current, current + size) ?;
235- current += size;
236- remaining -= size;
246+ match planner. plan_add_partition ( current, current + size) {
247+ Ok ( _) => {
248+ current += size;
249+ remaining -= size;
250+ }
251+ Err ( e) => {
252+ // Clean up any changes we made since we can't complete all requests
253+ while planner. has_changes ( ) {
254+ planner. undo ( ) ;
255+ }
256+ return Err ( e) ;
257+ }
258+ }
237259 }
238260
239261 Ok ( ( ) )
@@ -382,4 +404,67 @@ mod tests {
382404 let layout = planner. current_layout ( ) ;
383405 assert_eq ! ( layout. len( ) , 2 ) ;
384406 }
407+
408+ #[ test]
409+ fn test_insufficient_space ( ) {
410+ let disk = MockDisk :: new ( 10 * GB ) ; // Intentionally small disk
411+ let mut planner = Planner :: new ( & BlockDevice :: mock_device ( disk) ) ;
412+ let mut strategy = Strategy :: new ( AllocationStrategy :: InitializeWholeDisk ) ;
413+
414+ // Try to allocate more than available
415+ strategy. add_request ( PartitionRequest {
416+ size : SizeRequirement :: Exact ( 20 * GB ) ,
417+ } ) ;
418+
419+ assert ! ( strategy. apply( & mut planner) . is_err( ) ) ;
420+ }
421+
422+ #[ test]
423+ fn test_flexible_partition_overflow ( ) {
424+ let disk = MockDisk :: new ( 10 * GB ) ;
425+ let mut planner = Planner :: new ( & BlockDevice :: mock_device ( disk) ) ;
426+ let mut strategy = Strategy :: new ( AllocationStrategy :: InitializeWholeDisk ) ;
427+
428+ // Request more than available in flexible partitions
429+ strategy. add_request ( PartitionRequest {
430+ size : SizeRequirement :: AtLeast ( 6 * GB ) ,
431+ } ) ;
432+ strategy. add_request ( PartitionRequest {
433+ size : SizeRequirement :: AtLeast ( 6 * GB ) ,
434+ } ) ;
435+
436+ // Should fail because total minimum (12GB) exceeds disk size (10GB)
437+ let result = strategy. apply ( & mut planner) ;
438+ assert ! ( matches!( result, Err ( PlanError :: RegionOutOfBounds { .. } ) ) ) ;
439+ assert ! ( !planner. has_changes( ) ) ;
440+ }
441+
442+ #[ test]
443+ fn test_partial_partition_creation ( ) {
444+ let disk = MockDisk :: new ( 8 * GB ) ;
445+ let mut planner = Planner :: new ( & BlockDevice :: mock_device ( disk) ) ;
446+ let mut strategy = Strategy :: new ( AllocationStrategy :: InitializeWholeDisk ) ;
447+
448+ // Request sequence where first two would fit but third won't
449+ strategy. add_request ( PartitionRequest {
450+ size : SizeRequirement :: Range { min : GB , max : 2 * GB } ,
451+ } ) ;
452+ strategy. add_request ( PartitionRequest {
453+ size : SizeRequirement :: Range {
454+ min : 2 * GB ,
455+ max : 4 * GB ,
456+ } ,
457+ } ) ;
458+ strategy. add_request ( PartitionRequest {
459+ size : SizeRequirement :: Range {
460+ min : 25 * GB ,
461+ max : 120 * GB ,
462+ } ,
463+ } ) ;
464+
465+ // Should fail and undo partial changes
466+ let result = strategy. apply ( & mut planner) ;
467+ assert ! ( matches!( result, Err ( PlanError :: RegionOutOfBounds { .. } ) ) ) ;
468+ assert ! ( !planner. has_changes( ) , "Partial changes should be undone" ) ;
469+ }
385470}
0 commit comments