@@ -304,6 +304,63 @@ public void testThresholdBlocksMarginalMove()
304304 Assert .assertEquals ("DEST" , movedTo .getServer ().getName ());
305305 }
306306
307+ @ Test
308+ public void testNearFullServerIsNotChosenForNewSegmentLoad ()
309+ {
310+ final long maxSize = 10_000_000L ;
311+ // A: 95% full, 5 same-DS DAY segments -> raw cost = 10 * K (low, few co-located segs)
312+ final ServerHolder nearFull = buildServer ("A" , maxSize , 9_500_000L , 0 , 5 );
313+ // B: 70% full, 20 same-DS DAY segments -> raw cost = 40 * K (higher, more co-located)
314+ final ServerHolder partial = buildServer ("B" , maxSize , 7_000_000L , 100 , 20 );
315+
316+ final DataSegment newSegment = getSegment (1000 );
317+ final List <ServerHolder > servers = new ArrayList <>();
318+ servers .add (nearFull );
319+ servers .add (partial );
320+
321+ // CostBalancerStrategy picks A because raw cost 10K < 40K.
322+ Assert .assertEquals (
323+ "Pure CostBalancerStrategy must pick the near-full server (lower raw cost)" ,
324+ "A" ,
325+ newCostStrategy ().findServersToLoadSegment (newSegment , servers ).next ().getServer ().getName ()
326+ );
327+
328+ // DiskNormalized: A_norm = 10K / 0.05 = 200K, B_norm = 40K / 0.30 = 133K -> B wins.
329+ Assert .assertEquals (
330+ "DiskNormalized must prefer the emptier server despite its higher raw cost" ,
331+ "B" ,
332+ newDiskNormalizedStrategy ().findServersToLoadSegment (newSegment , servers ).next ().getServer ().getName ()
333+ );
334+ }
335+
336+ @ Test
337+ public void testNearFullServerIsNotChosenAsMoveDestination ()
338+ {
339+ final long maxSize = 10_000_000L ;
340+ // SOURCE: 70% full, 20 same-DS DAY segments; segmentToMove is one of them.
341+ final ServerHolder source = buildServer ("SOURCE" , maxSize , 7_000_000L , 0 , 20 );
342+ // DEST: 95% full, 5 same-DS DAY segments -> raw cost 10K < SOURCE's 38K.
343+ final ServerHolder nearFullDest = buildServer ("DEST" , maxSize , 9_500_000L , 100 , 5 );
344+
345+ final DataSegment segmentToMove = getSegment (0 );
346+ final List <ServerHolder > servers = new ArrayList <>();
347+ servers .add (source );
348+ servers .add (nearFullDest );
349+
350+ // CostBalancerStrategy: DEST raw cost (10K) < SOURCE raw cost (38K) -> recommends the move.
351+ final ServerHolder costResult =
352+ newCostStrategy ().findDestinationServerToMoveSegment (segmentToMove , source , servers );
353+ Assert .assertNotNull ("CostBalancerStrategy must recommend moving to the near-full DEST" , costResult );
354+ Assert .assertEquals ("DEST" , costResult .getServer ().getName ());
355+
356+ // DiskNormalized: DEST_norm = 10K / 0.05 = 200K > SOURCE_norm = 38K / 0.30 * 0.95 ≈ 120K.
357+ // Near-full DEST is too expensive after normalization -> no move.
358+ Assert .assertNull (
359+ "DiskNormalized must block the move to the near-full server" ,
360+ newDiskNormalizedStrategy ().findDestinationServerToMoveSegment (segmentToMove , source , servers )
361+ );
362+ }
363+
307364 @ Test
308365 public void testRejectsInvalidThreshold ()
309366 {
0 commit comments