@@ -265,3 +265,97 @@ func TestBalancesCleanup(t *testing.T) {
265265 // Now balance for mid1 should be cleaned as well
266266 assert .Nil (b .Balance (mid1 ))
267267}
268+
269+ func TestAddressBalances_CompareAndUpdateBalance (t * testing.T ) {
270+ addr := ethcommon .BytesToAddress ([]byte ("foo" ))
271+ mid := ManifestID ("some manifestID" )
272+ balances := NewAddressBalances (1 * time .Minute )
273+ defer balances .StopCleanup ()
274+
275+ assert := assert .New (t )
276+
277+ // Test 1: Balance doesn't exist - should initialize to 1 and then update to expected
278+ expected := big .NewRat (10 , 1 )
279+ minimumBal := big .NewRat (5 , 1 )
280+ current , diff , minimumBalCovered , resetToZero := balances .CompareAndUpdateBalance (addr , mid , expected , minimumBal )
281+
282+ assert .Zero (expected .Cmp (current ), "Balance should be updated to expected value" )
283+ assert .Zero (big .NewRat (10 , 1 ).Cmp (diff ), "Diff should be expected - initial (10 - 1)" )
284+ assert .True (minimumBalCovered , "Minimum balance should be covered when going from 1 to 10" )
285+ assert .False (resetToZero , "Should not be reset to zero" )
286+
287+ // Test 2: Expected > Current (Credit scenario)
288+ expected = big .NewRat (20 , 1 )
289+ minimumBal = big .NewRat (15 , 1 )
290+ current , diff , minimumBalCovered , resetToZero = balances .CompareAndUpdateBalance (addr , mid , expected , minimumBal )
291+
292+ assert .Zero (expected .Cmp (current ), "Balance should be updated to expected value" )
293+ assert .Zero (big .NewRat (10 , 1 ).Cmp (diff ), "Diff should be 20 - 10 = 10" )
294+ assert .True (minimumBalCovered , "Minimum balance should be covered when crossing threshold" )
295+ assert .False (resetToZero , "Should not be reset to zero" )
296+
297+ // Test 3: Expected < Current (Debit scenario)
298+ expected = big .NewRat (5 , 1 )
299+ minimumBal = big .NewRat (3 , 1 )
300+ current , diff , minimumBalCovered , resetToZero = balances .CompareAndUpdateBalance (addr , mid , expected , minimumBal )
301+
302+ assert .Zero (expected .Cmp (current ), "Balance should be updated to expected value" )
303+ assert .Zero (big .NewRat (- 15 , 1 ).Cmp (diff ), "Diff should be 5 - 20 = -15" )
304+ assert .True (minimumBalCovered , "Minimum balance should still be covered" )
305+ assert .False (resetToZero , "Should not be reset to zero" )
306+
307+ // Test 4: Expected == Current (No change)
308+ expected = big .NewRat (5 , 1 )
309+ minimumBal = big .NewRat (3 , 1 )
310+ current , diff , minimumBalCovered , resetToZero = balances .CompareAndUpdateBalance (addr , mid , expected , minimumBal )
311+
312+ assert .Zero (expected .Cmp (current ), "Balance should remain the same" )
313+ assert .Zero (big .NewRat (0 , 1 ).Cmp (diff ), "Diff should be 0" )
314+ assert .True (minimumBalCovered , "Minimum balance should still be covered" )
315+ assert .False (resetToZero , "Should not be reset to zero" )
316+
317+ // Test 5: Reset to zero (current > 0, expected = 0)
318+ balances .Credit (addr , mid , big .NewRat (5 , 1 )) // Set current to 10
319+ expected = big .NewRat (0 , 1 )
320+ minimumBal = big .NewRat (3 , 1 )
321+ current , diff , minimumBalCovered , resetToZero = balances .CompareAndUpdateBalance (addr , mid , expected , minimumBal )
322+
323+ assert .Zero (expected .Cmp (current ), "Balance should be reset to zero" )
324+ assert .Zero (big .NewRat (- 10 , 1 ).Cmp (diff ), "Diff should be 0 - 10 = -10" )
325+ assert .False (minimumBalCovered , "Minimum balance should not be covered when resetting to zero" )
326+ assert .True (resetToZero , "Should be marked as reset to zero" )
327+
328+ // Test 6: Minimum balance covered threshold - just below to just above
329+ expected = big .NewRat (2 , 1 )
330+ minimumBal = big .NewRat (5 , 1 )
331+ balances .CompareAndUpdateBalance (addr , mid , expected , minimumBal ) // Set to 2
332+
333+ expected = big .NewRat (5 , 1 )
334+ current , diff , minimumBalCovered , resetToZero = balances .CompareAndUpdateBalance (addr , mid , expected , minimumBal )
335+
336+ assert .Zero (expected .Cmp (current ), "Balance should be updated to 5" )
337+ assert .Zero (big .NewRat (3 , 1 ).Cmp (diff ), "Diff should be 5 - 2 = 3" )
338+ assert .True (minimumBalCovered , "Minimum balance should be covered when crossing from below to at threshold" )
339+ assert .False (resetToZero , "Should not be reset to zero" )
340+
341+ // Test 7: Minimum balance not covered - already above threshold
342+ expected = big .NewRat (10 , 1 )
343+ minimumBal = big .NewRat (5 , 1 )
344+ current , diff , minimumBalCovered , resetToZero = balances .CompareAndUpdateBalance (addr , mid , expected , minimumBal )
345+
346+ assert .Zero (expected .Cmp (current ), "Balance should be updated to 10" )
347+ assert .Zero (big .NewRat (5 , 1 ).Cmp (diff ), "Diff should be 10 - 5 = 5" )
348+ assert .True (minimumBalCovered , "Minimum balance should still be covered" )
349+ assert .False (resetToZero , "Should not be reset to zero" )
350+
351+ // Test 8: Negative balance handling
352+ balances .Debit (addr , mid , big .NewRat (20 , 1 )) // Force negative: 10 - 20 = -10
353+ expected = big .NewRat (5 , 1 )
354+ minimumBal = big .NewRat (3 , 1 )
355+ current , diff , minimumBalCovered , resetToZero = balances .CompareAndUpdateBalance (addr , mid , expected , minimumBal )
356+
357+ assert .Zero (expected .Cmp (current ), "Balance should be updated to expected value" )
358+ assert .Zero (big .NewRat (15 , 1 ).Cmp (diff ), "Diff should be 5 - (-10) = 15" )
359+ assert .True (minimumBalCovered , "Minimum balance should be covered when going from negative to positive above minimum" )
360+ assert .False (resetToZero , "Should not be reset to zero" )
361+ }
0 commit comments