Ë
    ƒÝjÖ  ã                   ó(  — d Z ddlZddlZddlZddlZddlZddlmZ ddlm	Z	m
Z
 ddlmZ ddlmZmZ  e ee«      j%                  «       j&                  d   «      Z G d„ d	ej*                  «      Z G d
„ de«      Zedk(  r ej2                  «        yy)uT   Budget: Reservierung vor, Abrechnung nach der AusfÃ¼hrung; persistent; nebenlÃ¤ufig.é    N)ÚPath)ÚBudgetLedgerÚBudgetLimit)ÚHandling)Ú	FakeClockÚGatewayTestCaseé   c                   ó\   — e Zd Zd„ Zd„ Zdd„Zd„ Zd„ Zd„ Zd„ Z	d	„ Z
d
„ Zd„ Zd„ Zd„ Zd„ Zy)ÚBudgetLedgerTestsc                 ó¢   — t        j                  «       | _        t        | j                  j                  «      dz  | _        t        «       | _        y )Nzbudget.json)ÚtempfileÚTemporaryDirectoryÚ_tmpr   ÚnameÚpathr   Úclock©Úselfs    ú2/home/aria/aria-v3-dev/python/tests/test_budget.pyÚsetUpzBudgetLedgerTests.setUp   s4   € Ü×/Ñ/Ó1ˆŒ	Ü˜Ÿ™Ÿ™Ó(¨=Ñ8ˆŒ	Ü“[ˆ�
ó    c                 ó8   — | j                   j                  «        y )N)r   Úcleanupr   s    r   ÚtearDownzBudgetLedgerTests.tearDown   s   € Ø�	‰	×ÑÕr   Nc                 ó^   — t        | j                  dt        ||«      i| j                  ¬«      S )NÚcodex©r   )r   r   r   r   )r   ÚjobsÚtokenss      r   ÚledgerzBudgetLedgerTests.ledger   s(   € Ü˜DŸI™I¨´¸TÀ6Ó1JÐ'KÐSW×S]ÑS]Ô^Ð^r   c                 ó*  — | j                  d«      }dD ]7  }| j                  |j                  d|d«      «       |j                  |d¬«       Œ9 | j	                  |j                  ddd«      «       | j                  |j                  d«      d   d«       y )	Né   )ÚaÚbr   r	   T©ÚconsumedÚcr   )r    Ú
assertTrueÚreserveÚsettleÚassertFalseÚassertEqualÚusage_today)r   r    Újobs      r   Útest_reserve_and_settle_countsz0BudgetLedgerTests.test_reserve_and_settle_counts   s„   € Ø—‘˜Q“ˆØò 	.ˆCØ�O‰O˜FŸN™N¨7°C¸Ó;Ô<Ø�M‰M˜#¨ˆMÕ-ð	.ð 	×Ñ˜Ÿ™¨°°aÓ8Ô9Ø×Ñ˜×+Ñ+¨GÓ4°VÑ<¸aÕ@r   c                 ó  — | j                  d«      }| j                  |j                  ddd«      «       |j                  dd¬«       | j	                  |j                  d«      d   d«       | j                  |j                  ddd«      «       y )	Nr	   r   r#   Fr%   r   r   r$   )r    r(   r)   r*   r,   r-   ©r   r    s     r   Útest_release_when_not_consumedz0BudgetLedgerTests.test_release_when_not_consumed%   sq   € Ø—‘˜Q“ˆØ�‰˜Ÿ™ w°°QÓ7Ô8Ø�‰�c EˆÔ*Ø×Ñ˜×+Ñ+¨GÓ4°VÑ<¸aÔ@Ø�‰˜Ÿ™ w°°QÓ7Õ8r   c                 óî   — | j                  d«      }| j                  |j                  ddd«      «       | j                  |j	                  d«      «       | j                  |j                  ddd«      «       y )Nr	   r   r#   r$   )r    r(   r)   r+   Ú	availabler1   s     r   Ú-test_pending_reservation_counts_against_limitz?BudgetLedgerTests.test_pending_reservation_counts_against_limit,   s\   € Ø—‘˜Q“ˆØ�‰˜Ÿ™ w°°QÓ7Ô8Ø×Ñ˜×)Ñ)¨'Ó2Ô3Ø×Ñ˜Ÿ™¨°°aÓ8Õ9r   c                 óØ   — | j                  d«      }|j                  ddd«       |j                  dd¬«       | j                  | j                  d«      j	                  d«      d   d«       y )Né   r   r#   r	   Tr%   r   )r    r)   r*   r,   r-   )r   Úfirsts     r   Ú!test_persistence_across_instancesz3BudgetLedgerTests.test_persistence_across_instances2   sW   € Ø—‘˜A“ˆØ�‰�g˜s AÔ&Ø�‰�S 4ˆÔ(Ø×Ñ˜Ÿ™ Q›×3Ñ3°GÓ<¸VÑDÀaÕHr   c                 óö   — | j                  dd¬«      }| j                  |j                  ddd«      «       | j                  |j                  ddd«      «       | j                  |j                  ddd	«      «       y )
Né
   )r   r   r#   é   r$   r7   r'   r"   )r    r(   r)   r+   r1   s     r   Útest_token_estimate_limitz+BudgetLedgerTests.test_token_estimate_limit8   sa   € Ø—‘˜R¨�Ó+ˆØ�‰˜Ÿ™ w°°QÓ7Ô8Ø×Ñ˜Ÿ™¨°°aÓ8Ô9Ø�‰˜Ÿ™ w°°QÓ7Õ8r   c                 ó,  — | j                  d«      }|j                  ddd«       |j                  dd¬«       | j                  |j	                  d«      «       | j
                  j                  d«       | j                  |j                  ddd«      «       y )Nr	   r   r#   Tr%   i€Q r$   )r    r)   r*   r+   r4   r   Úadvancer(   r1   s     r   Útest_day_rollover_utcz'BudgetLedgerTests.test_day_rollover_utc>   ss   € Ø—‘˜Q“ˆØ�‰�w  QÔ'Ø�‰�c DˆÔ)Ø×Ñ˜×)Ñ)¨'Ó2Ô3Ø�
‰
×Ñ˜5Ô!Ø�‰˜Ÿ™ w°°QÓ7Õ8r   c                 óª   — | j                  d«      }| j                  |j                  d«      «       | j                  |j                  ddd«      «       y )Nr7   Úclauder#   r	   )r    r+   r4   r)   r1   s     r   Ú test_unconfigured_backend_deniedz2BudgetLedgerTests.test_unconfigured_backend_deniedF   sC   € Ø—‘˜Q“ˆØ×Ñ˜×)Ñ)¨(Ó3Ô4Ø×Ñ˜Ÿ™¨°#°qÓ9Õ:r   c                 ó  — | j                  d«      }|j                  ddd«       | j                  j                  d«       | j	                  |j                  ddd«      «       | j                  |j                  d«      d   d«       y )Nr	   r   zcrashed-jobi  r$   r   )r    r)   r   r?   r+   r,   r-   r1   s     r   Ú&test_stale_reservation_counted_as_usedz8BudgetLedgerTests.test_stale_reservation_counted_as_usedK   sl   € Ø—‘˜Q“ˆØ�‰�w ¨qÔ1Ø�
‰
×Ñ˜4Ô Ø×Ñ˜Ÿ™¨°°aÓ8Ô9Ø×Ñ˜×+Ñ+¨GÓ4°VÑ<¸aÕ@r   c                 óÖ  ‡ ‡‡‡— ‰ j                  d«      }t        j                  d«      Šg Št        j                  «       Šˆˆˆˆ fd„}t	        d«      D �cg c]  }t        j
                  ||f¬«      ‘Œ }}|D ]  }|j                  «        Œ |D ]  }|j                  d«       Œ ‰ j                  t        ‰«      d«       ‰ j                  |j                  d«      d   d«       y c c}w )Nr7   é   c                 óø   •— ‰j                  «        t        ‰j                  dt        d«      i‰j                  ¬«      j                  dd| › �d«      }‰5  ‰j                  |«       d d d «       y # 1 sw Y   y xY w)Nr   r7   r   zjob-r	   )Úwaitr   r   r   r   r)   Úappend)ÚindexÚgrantedÚbarrierÚlockÚresultsr   s     €€€€r   ÚworkerzFBudgetLedgerTests.test_concurrent_reservations_threads.<locals>.workerX   sg   ø€ Ø�L‰LŒNÜ" 4§9¡9¨w¼ÀA»Ð.GÈtÏzÉzÔZ×bÑbØ˜4 ˜w˜¨ó,ˆGàñ (Ø—‘˜wÔ'÷(÷ (ñ (ús   ÁA0Á0A9)ÚtargetÚargsé   r   r   )r    Ú	threadingÚBarrierÚLockÚrangeÚThreadÚstartÚjoinr,   Úsumr-   )	r   r    rP   ÚiÚthreadsÚthreadrM   rN   rO   s	   `     @@@r   Ú$test_concurrent_reservations_threadsz6BudgetLedgerTests.test_concurrent_reservations_threadsR   sÌ   û€ Ø—‘˜Q“ˆÜ×#Ñ# BÓ'ˆØˆÜ�~‰~Óˆ÷	(ô HMÈRÃyÖQÀ!”9×#Ñ#¨6¸¸Ö=ÐQˆÐQØò 	ˆFØ�L‰L�Nð	àò 	ˆFØ�K‰K˜�Oð	à×Ñœ˜W› qÔ)Ø×Ñ˜×+Ñ+¨GÓ4°VÑ<¸aÕ@ùò Rs   ÁC&c                 ó0  — d}t        d«      D �cg c]W  }t        j                  t        j                  dd|t
        t        | j                  «      d|› �gt        j                  d¬«      ‘ŒY }}t        d„ |D «       «      }| j                  |d	«       y c c}w )
Na-  import sys; sys.path.insert(0, sys.argv[1])
from pathlib import Path
from aria_router.budget import BudgetLedger, BudgetLimit
ledger = BudgetLedger(Path(sys.argv[2]), {'codex': BudgetLimit(5)}, clock=lambda: 1800000000.0)
print(sum(ledger.reserve('codex', f'{sys.argv[3]}-{i}', 1) for i in range(4)))
é   z-Iz-cÚpT)ÚstdoutÚtextc              3   ót   K  — | ]0  }t        |j                  d ¬«      d   j                  «       «      –— Œ2 y­w)é<   )Útimeoutr   N)ÚintÚcommunicateÚstrip)Ú.0rb   s     r   ú	<genexpr>zKBudgetLedgerTests.test_concurrent_reservations_processes.<locals>.<genexpr>q   s.   è ø€ ÒOÀA”c˜!Ÿ-™-°˜-Ó3°AÑ6×<Ñ<Ó>×?ÑOùs   ‚68r7   )rW   Ú
subprocessÚPopenÚsysÚ
executableÚPACKAGE_ROOTÚstrr   ÚPIPEr[   r,   )r   Úcoder\   ÚprocsrL   s        r   Ú&test_concurrent_reservations_processesz8BudgetLedgerTests.test_concurrent_reservations_processesg   s�   € ð_ð 	ô OTÐTUËhöXØIJô ×!Ñ!¤3§>¡>°4¸¸tÄ\ÔSVÐW[×W`ÑW`ÓSaÐefÐghÐfiÐcjÐ"kÜ)3¯©¸töEð Xˆð XäÑOÈÔOÓOˆØ×Ñ˜ !Õ$ùòXs   �AB)r"   N)Ú__name__Ú
__module__Ú__qualname__r   r   r    r/   r2   r5   r9   r=   r@   rC   rE   r_   rv   © r   r   r   r      sH   „ ò!ò
ó_òAò9ò:òIò9ò9ò;ò
AòAó*%r   r   c                   ó*   — e Zd Zd„ Zd„ Zd„ Zd„ Zd„ Zy)ÚGatewayBudgetTestsc                 ó
  — | j                  ddddiii«      }| j                  |j                  | j                  dd«      «      j                  d«       |j                  | j                  dd«      «      }| j                  |j
                  |j                  ft        j                  df«       | j                  d	|j                  «       | j                  t        |j                  d   j                  j                  «      d«       y )
NÚbudgetr   Ú
daily_jobsr	   z/codex #public ar"   z/codex #public bÚMANUAL_CHOICE_NOT_PERMITTEDÚTagesbudget)Úgatewayr,   ÚhandleÚrequestÚbackendÚhandlingrt   r   ÚBLOCKEDÚassertInÚ
reply_textÚlenÚadaptersÚrunnerÚcalls)r   r‚   Úresults      r   Ú)test_budget_exhausted_blocks_manual_codexz<GatewayBudgetTests.test_budget_exhausted_blocks_manual_codexv   sÎ   € Ø—,‘, ¨7°\À1Ð4EÐ*FÐGÓHˆØ×Ñ˜Ÿ™¨¯©°QÐ8JÓ(KÓL×TÑTÐV]Ô^Ø—‘ §¡¨QÐ0BÓ CÓDˆØ×Ñ˜&Ÿ/™/¨6¯;©;Ð7¼(×:JÑ:JÐLiÐ9jÔkØ�‰�m V×%6Ñ%6Ô7Ø×Ñœ˜W×-Ñ-¨gÑ6×=Ñ=×CÑCÓDÀaÕHr   c                 ó¤  — | j                  ddddiii«      }| j                  |j                  | j                  dd«      «      j                  d«       |j                  | j                  dd«      «      }| j                  |j                  d	«       | j                  |«      d
   }t        d„ |d   d   D «       «      }| j                  d|d   «       y )Nr~   r   r   r	   é   ú	#public ara   z	#public brB   éÿÿÿÿc              3   ó2   K  — | ]  }|d    dk(  sŒ|–— Œ y­w)r…   r   Nrz   )rk   r'   s     r   rl   zZGatewayBudgetTests.test_budget_exhausted_auto_routes_to_eligible_claude.<locals>.<genexpr>„   s   è ø€ Ò[˜1À1ÀYÁ<ÐSZÓCZ”QÑ[ùs   ‚�ÚroutingÚ
candidatesÚBUDGET_EXHAUSTEDÚreasons)r‚   r,   rƒ   r„   r…   Údecision_recordsÚnextrˆ   )r   r‚   rŽ   Úrecordr   s        r   Ú4test_budget_exhausted_auto_routes_to_eligible_claudezGGatewayBudgetTests.test_budget_exhausted_auto_routes_to_eligible_claude~   s¹   € Ø—,‘, ¨7°\À1Ð4EÐ*FÐGÓHˆØ×Ñ˜Ÿ™¨¯©°Q¸Ó(DÓE×MÑMÈwÔWØ—‘ §¡¨Q°Ó <Ó=ˆØ×Ñ˜Ÿ™¨Ô2Ø×&Ñ& wÓ/°Ñ3ˆÜÑ[  yÑ 1°,Ñ ?Ô[Ó[ˆØ�‰Ð(¨%°	Ñ*:Õ;r   c                 ó@  — | j                  ddddiii«      }| j                  dz  dz  j                  «        | j                  |j	                  | j                  dd«      «      j                  d	«       | j                  |j                  «       d
   d   d   d   d«       y )Nr~   r   r   r	   Úkeyszclearance.keyr7   r’   ÚKEY_UNAVAILABLEÚbackendsr   r   )r‚   ÚrootÚunlinkr,   rƒ   r„   rt   Ústatus)r   r‚   s     r   Ú&test_budget_released_when_not_executedz9GatewayBudgetTests.test_budget_released_when_not_executed‡   s�   € Ø—,‘, ¨7°\À1Ð4EÐ*FÐGÓHˆØ	�‰�VÑ	˜oÑ	-×5Ñ5Ô7Ø×Ñ˜Ÿ™¨¯©°Q¸Ó(DÓE×JÑJÐL]Ô^Ø×Ñ˜Ÿ™Ó)¨*Ñ5°gÑ>¸xÑHÈÑPÐRSÕTr   c           	      ó,  — | j                  ddddiii«      }dD ]=  }| j                  |j                  | j                  |d«      «      j                  d«       Œ? | j                  |j                  | j                  dd«      «      j                  d«       y )Nr~   r   r   r	   )é   é   r<   r’   é	   )r‚   r,   Úshadowr„   r…   rƒ   )r   r‚   Ú
message_ids      r   Ú#test_shadow_does_not_consume_budgetz6GatewayBudgetTests.test_shadow_does_not_consume_budget�   s…   € Ø—,‘, ¨7°\À1Ð4EÐ*FÐGÓHˆØ#ò 	eˆJØ×Ñ˜WŸ^™^¨D¯L©L¸À[Ó,QÓR×ZÑZÐ\cÕdð	eà×Ñ˜Ÿ™¨¯©°Q¸Ó(DÓE×MÑMÈwÕWr   c                 óD  ‡— ddl m}mŠ | j                  ddddiii |ˆfd„«      ¬«      }| j	                  |j                  | j                  d	d
«      «      j                  t        j                  «       | j	                  |j                  «       d   d   d   d   d«       y )Nr   )Ú
MockRunnerÚ	RunResultr~   r   r   r7   c                 ó   •—  ‰ddd¬«      S )NFÚNONZERO_EXITr	   )Ú	exit_coderz   )Úspecr®   s    €r   ú<lambda>zDGatewayBudgetTests.test_failed_run_consumes_budget.<locals>.<lambda>–   s   ø€ ÁIÈeÐUcÐopÔDq€ r   )Úcodex_runnerr;   r’   r    r   r	   )Úaria_router.runnerr­   r®   r‚   r,   rƒ   r„   r†   r   ÚFAILEDr£   )r   r­   r‚   r®   s      @r   Útest_failed_run_consumes_budgetz2GatewayBudgetTests.test_failed_run_consumes_budget“   s‘   ø€ ß<Ø—,‘, ¨7°\À1Ð4EÐ*FÐGÙ,6Ó7qÓ,rð ó tˆà×Ñ˜Ÿ™¨¯©°R¸Ó(EÓF×OÑOÔQY×Q`ÑQ`ÔaØ×Ñ˜Ÿ™Ó)¨*Ñ5°gÑ>¸xÑHÈÑPÐRSÕTr   N)rw   rx   ry   r�   rœ   r¤   r«   r·   rz   r   r   r|   r|   u   s   „ òIò<òUòXóUr   r|   Ú__main__)Ú__doc__rm   ro   r   rT   ÚunittestÚpathlibr   Úaria_router.budgetr   r   Úaria_router.gatewayr   Útests.helpersr   r   rr   Ú__file__ÚresolveÚparentsrq   ÚTestCaser   r|   rw   Úmainrz   r   r   ú<module>rÄ      sƒ   ðÙ ZÛ Û 
Û Û Û Ý ç 8Ý (ç 4á‘4˜“>×)Ñ)Ó+×3Ñ3°AÑ6Ó7€ôa%˜×)Ñ)ô a%ôH#U˜ô #UðL ˆzÒØ€H‡M�M…Oð r   