o
    ʺ
j!                  
   @   s  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ZddlZddlZddl	Z	zej
jddd ejjddd W n	 eyA   Y nw e	e jjZejdee e	e d Zejeedd ejddd	 eed
 Zeejd< ddlZee_ddlZe  ddl Z!e!j Z"de"_#e$de%dd e"j&' D  dmddZ(dd Z)dnddZ*dd Z+dd Z,e$d e(dddZ-e". Z/e)e/e- e+e/Z0e*e0g dd e/1d e0 Z2e$d!e2j3  e$d"e2j41d#  e$d$e5e2j6  e2j3d%ksJ d&e2j3 d'e2j6dd( e2j41d#d)ksJ e7e8e2j6Z9e9: Z;e$d*e;  e5e;d+ks>J d,e; e2j4<d-Z=e>d.d e=D Z?e$d/e?  e?s^J d0e= W d   n	1 siw   Y  e,e-Z@e$d1e@ d2 e@dk sJ e$d3 e(d4d5dZAe". \Z/e)e/eA e+e/Z0e*e0g dd e/1d e0 Z2e$d!e2j3  e2B ZCe$d6eCreC1d7nd8  e2j3d9ksJ d:e2j3 d'e2j6dd( eC1d7d;ksJ W d   n	1 sw   Y  e,eAZDe$d1eD d< eDd5ksJ d=eD e$d> e(d?d@dZEe". \Z/e)e/eE e+e/Z0e*e0g dd ejFeEdAdBdC e/1d e0 Z2e$d!e2j3  e2B ZCe$dDeCrReC1dEnd8  e2j3dFkseJ dGe2j3 eC1dEdu soJ W d   n	1 szw   Y  e,eEZGe$d1eG dH eGd@ksJ e$dI e(dJddZHe". Z/e)e/eH e+e/Z0e*e0dKdLgd e,eHZIe/1d e0 Z2e$d!e2j3  e2j3d%ksJ dMe2j6dd( e7e8e2j6Z9e9: Z;e$d*e;  e>dNd e;D ZJe>dOd e;D ZKe>dPd e;D ZLe>dQd e;D ZMe$dReL dSeM dTeK dUeJ  eLr,eMr,eJs,eKr3J dVe; W d   n	1 s>w   Y  e,eHZNe$dWeIeN  dX de@ ZOeIeN ZPe$dYeO dZeP  ePeOksrJ d[eP d\eO e$d] e(d^ddZQe!jRZSdod_d`ZTeTe!_Rzne". DZ/e)e/eQ e+e/Z0e*e0g dd e/1d e0 Z2e$d!e2j3  e2B ZCe$daeCreC1dbnd8  e2j3d@ksJ W d   n	1 sw   Y  e,eQZUe$d1eU dc eUdksJ ddeU W eSe!_RneSe!_Rw e$de e(dfddZVe". PZ/e)e/eV e+e/Z0e*e0g dd e/1d e0 ZWeWj3d%ks*J ddlXZXeXYdg e/1d e0 ZZe$dheZj3  eZj3div sQJ djeZj3 W d   n	1 s\w   Y  e,eVZ[e$d1e[ dk e$dl dS )pzHEnd-to-end test for Phase 5: Atomic token deduction on /api/v1/download.    Nzutf-8replace)encodingerrorsabrechnung_test_p5T)ignore_errorsparentsexist_okzlicensing.sqlite3ABRECHNUNG_LICENSE_DBz	v1 rules:c                 c   s    | ]
}d |j v rdV  qdS )z/api/v1/   N)rule).0r r   g/sessions/sharp-trusting-curie/mnt/energie-durchdacht/EEG-Abrechnung/v1.07b_upload/tests/test_phase5.py	<genexpr>   s    r     c                 C   s   t | d d |S N)	licensingcreate_account)nametokensr   r   r   fresh_account!   s   r   c                 C   sL   | j d|dtd  dd}|jdkr"td|j d|j| S )	Nz/api/v1/loginzfp-test-   )uidfingerprint)json   zLogin failed:  )postosurandomhexstatus_codeRuntimeErrordataget_json)clientr   rvr   r   r   do_login%   s   

r)   2024c                 C   s   t tj| }|d }|| jddd || d d || d d |d d	 |d
 jdd |d
 d d |d jdd |d d d tj| }d|d< d|i|d< |durmt||d< dS dS )z<Create a 'done' session matching what main.py would produce.
RechnungenTr   zRechnung_001.pdfs   %PDF-1.4 dummy 1zRechnung_002.pdfs   %PDF-1.4 dummy 2zKassabuch.xlsxs   dummy xlsx kassabuchSEPA)r	   zSEPA_2024.xmls    <?xml version="1.0"?><Document/>ReportzGemeinschaftsbericht.pdfs   %PDF-1.4 reportdonestatusperioder%   Nmodules)	pathlibPath
app_modulesmtemp_dirmkdirwrite_bytesgetlist)sidr0   r1   tdr   sessr   r   r   seed_session_done/   s    r>   c                 C   s8   |  d}|jdkrtd|j d|j| d S )Nz/api/v1/session/newr   zsession/new failed: r   r;   )r   r#   r$   r%   r&   )r'   r(   r   r   r   new_sessionF   s   

r?   c                 C   s.   t jddD ]}|d | kr|d   S qd S )NT)include_disabledr   remaining_tokens)r   list_accounts)r   ar   r   r   
balance_ofM   s
   rD   z:
=== Scenario 1: Happy path (1000 tokens, all modules) ===zKunde-S1)r   )pdfsreport	kassabuchsepa)r1   z/api/v1/download?sid=z  HTTP: z  Content-Type: zContent-Typez	  Bytes: r   zExpected 200, got z: i,  zapplication/zipz  ZIP entries:    zExpected 5 files in ZIP, got z
Set-Cookiec                 c   s(    | ]}d |v od|v pd|v V  qdS )zlicense_session=zExpires=Thu, 01 Jan 1970z	Max-Age=0Nr   )r   scr   r   r   r   g   s   & z  Cookie cleared: zLicense cookie NOT cleared: z  Balance after: z (was 1000)z:
=== Scenario 2: Insufficient tokens (1 token balance) ===zKunde-S2r   z
  reason: reasonz--i  zExpected 402, got 	no_tokensz& (should still be 1 - atomic rollback)zBalance changed on failure: zD
=== Scenario 3: Account disabled post-login (decorator rejects) ===zKunde-S3i  disabledtest)
admin_userz  need_login: 
need_login  zExpected 401, got z (should still be 500)z5
=== Scenario 4: Module subset (pdfs+report only) ===zKunde-S4rE   rF   zBody: c                 c       | ]}d |v V  qdS )r,   Nr   r   nr   r   r   r          c                 c   rR   )	KassabuchNr   rS   r   r   r   r      rU   c                 c   s$    | ]}| d o|dV  qdS )zRechnungen/z.pdfN)
startswithendswithrS   r   r   r   r      s   " c                 c   s    | ]}| d V  qdS )zGemeinschaftsbericht/N)rW   rS   r   r   r   r      s    z  pdfs=z report=z kassabuch=z sepa=zFilter broken: z  Deducted: z* tokens (subset, should be less than full)z  Full-set deducted: z, subset deducted: zSubset cost more than full?! z vs z?
=== Scenario 5: _build_zip raises exception - NO deduction ===zKunde-S5c                 C   s   t d)NzSimulierter ZIP-Fehler)r$   )r<   r0   r1   r   r   r   
broken_zip   s   rY   z	  error: errorz  (should still be 1000 - atomic)z%Tokens deducted despite ZIP failure: zL
=== Scenario 6: Session destroyed after successful download (no replay) ===zKunde-S6g333333?z  Second request HTTP: )rQ   i  zReplay should fail, got z (one deduction only)z!
=== ALL PHASE 5 TESTS PASSED ===)r   )r*   Nr   )\__doc__r    systempfileshutilr   iozipfile	importlibr2   stdoutreconfigurestderr	Exceptionr3   __file__resolveparentAPP_DIRpathinsertstr
gettempdir	TEST_ROOTrmtreer7   TEST_DBenvironsession_manager	TEMP_BASEr   init_dbappr4   	flask_apptestingprintsumurl_map
iter_rulesr   r)   r>   r?   rD   uid1test_clientcr;   r9   r(   r#   headerslenr%   ZipFileBytesIOzfnamelistnamesgetlistset_cookiesanyclearedbal1uid2r&   bodybal2uid3
set_statusbal3uid4
bal_beforehas_sepa	has_kassahas_pdfhas_repbal4full_deductedsubset_deducteduid5
_build_ziporig_build_ziprY   bal5uid6rv1timesleeprv2bal6r   r   r   r   <module>   s&   H





,

,




$ (


	


