
    t7j                    t   S r SSKJr  SSKrSSKJs  Jr  SSK	r	SSK
r
SSKrSSKJr  \
R                  R                  S\" \" \5      R%                  5       R&                  S   S-  5      5        SS jrS rS	 rS
 rS rS rS rS rS rS rS r\S:X  a  SSK r \!" \"" 5       RG                  5       5       V Vs/ s H  u  pU RI                  S5      (       d  M  UPM!     snn r%Sr&\% Hc  r' S\'RP                  RR                  ;   a)  \RT                  " 5        r+\'" \" \+5      5        SSS5        O\'" 5         \," S\'R>                   35        Me     \
R^                  " \&(       a  SOS5        ggs  snn f ! , (       d  f       NJ= f! \- a/    \&S-  r&\," S\'R>                   35        \ R\                  " 5          M  f = f)a  Basic smoke tests for the WolfPanel Agent v1 foundation.

Run with:  python -m pytest tests/   (or: python tests/test_basic.py)

These tests use a temporary WOLFPANEL_DEV_HOME so nothing touches real system
paths, and the mock API so no network is required.
    )annotationsN)Path   srcc                    U [         R                  S'   S[         R                  S'   SS KnSS KnUR	                  U5        UR                  5       $ )NWOLFPANEL_DEV_HOME1WOLFPANEL_API_MOCKr   )osenviron	importlibconfigreloadload_config)tmpr   config_modules      7D:\laragon\www\wolf\wolfpanel-agent\tests\test_basic.py_fresh_configr      sC    '*BJJ#$'*BJJ#$"]#$$&&    c                 J   [         R                  " 5        n [        U 5      nUR                  n[	        U5      o3R
                  oD" U 5      oU(       Gdb  SS[        R                  " 5       ;   d  [        R                  " [        5      (       a  [        R                  " [        5      OSS[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      S[        R                  " 5       ;   d  [        R                  " U 5      (       a  [        R                  " U 5      OS[        R                  " U5      S.-  n[        [        R                  " U5      5      eS =n=n=pEUR                  owR                  nSoHU:H  o(       d  [        R                  " SU	4SX45      S[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      S	.-  n
S
SU
0-  n[        [        R                  " U5      5      eS =n=n=pUR                   nSo7U:H  o(       d  [        R                  " SU4SXs45      S[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS[        R                  " U5      [        R                  " U5      S.-  nSSU0-  n
[        [        R                  " U
5      5      eS =n=pS S S 5        g ! , (       d  f       g = f)Nzassert %(py10)s
{%(py10)s = %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.conf_file
})
}.startswith
}(%(py8)s)
}strcfgr   )py0py1py3py5py7py8py10secrets==)zM%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.secrets_dir
}.name
} == %(py7)sr   py2py4r   assert %(py9)spy9<   )z:%(py2)s
{%(py2)s = %(py0)s.heartbeat_interval
} == %(py5)sr   r$   r   assert %(py7)sr   )tempfileTemporaryDirectoryr   	conf_filer   
startswith@py_builtinslocals
@pytest_ar_should_repr_global_name	_safereprAssertionError_format_explanationsecrets_dirname_call_reprcompareheartbeat_interval)r   r   @py_assert2@py_assert4@py_assert6@py_assert9@py_format11@py_assert1@py_assert3@py_assert5@py_format8@py_format10@py_format6s                r    test_config_paths_under_dev_homerE      s   		$	$	&#C ==1s=!1,,1,S111111111s1111s111111311113111=111!111,111111S1111S11111111110##0y0y00000#000000s0000s000000#000y0000000%%+++++++%++++++s++++s+++%++++++++++	 
'	&	&s   M5N
N"c                    SSK Jn   U " 5       nU " 5       nX:H  o3(       d  [        R                  " SU4SX45      S[        R
                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OSS[        R
                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OSS.-  nSS	U0-  n[        [        R                  " U5      5      eS nUR                  nS
oc" U5      ow(       d  SS[        R
                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      S.-  n[        [        R                  " U5      5      eS =n=pgg )Nr   )generate_fingerprintr!   )z%(py0)s == %(py2)sfp1fp2r   r$   assert %(py4)sr%   fp_zLassert %(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.startswith
}(%(py4)s)
}r   r$   r%   py6)identityrG   r1   r8   r/   r0   r2   r3   r4   r5   r.   )	rG   rH   rI   r?   @py_format3@py_format5r@   rA   @py_format7s	            r   %test_fingerprint_is_stable_and_opaquerS   &   s    -

 C

 C:333##>> % >%         3    3   >   %          r   c                    [         R                  " 5        n [        U 5      nSSKJn  SSKJnJnJn  U" U5        U" U5      R                  SSS.5      nU" U[        US   5      US   5        UR                  owR                  o" 5       oR                  o" 5       nS	oU:H  o(       Gd  [        R                  " S
U4SX45      S[         R"                  " 5       ;   d  [        R$                  " U5      (       a  [        R&                  " U5      OS[        R&                  " U5      [        R&                  " U5      [        R&                  " U	5      [        R&                  " U
5      [        R&                  " U5      [        R&                  " U5      S.-  nSSU0-  n[)        [        R*                  " U5      5      eS =n=n=n	=n
=n=pU" U5      nS	n	UU	:H  nU(       Gd  [        R                  " S
U4SUU	45      S[         R"                  " 5       ;   d  [        R$                  " U5      (       a  [        R&                  " U5      OSS[         R"                  " 5       ;   d  [        R$                  " U5      (       a  [        R&                  " U5      OS[        R&                  " U5      [        R&                  " U	5      S.-  nSSU0-  n[)        [        R*                  " U5      5      eS =n=nn	[-        U 5      R/                  S5       GH>  nUR1                  5       (       d  M  UUR                  :X  a  M-  SnUR                  nSnU" US9nUU;  nU(       d  [        R                  " SU4SUU45      [        R&                  " U5      S[         R"                  " 5       ;   d  [        R$                  " U5      (       a  [        R&                  " U5      OS[        R&                  " U5      [        R&                  " U5      [        R&                  " U5      S.-  nSSU0-  n[)        [        R*                  " U5      5      eS =n=n=n=nnGMA     S S S 5        g ! , (       d  f       g = f)Nr   get_api_client)ensure_dirsload_agent_tokenstore_credentialstfp_x)hostnamefingerprint	server_idagent_tokenwp_agent_dev_tokenr!   )z%(py10)s
{%(py10)s = %(py8)s
{%(py8)s = %(py6)s
{%(py6)s = %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.agent_token_file
}.read_text
}()
}.strip
}()
} == %(py13)sr   )r   r$   r%   rN   r   r   py13zassert %(py15)spy15)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)srX   )r   r   r   rN   zassert %(py8)sr   *install_tokenignore)errorsnot in)zZ%(py1)s not in %(py9)s
{%(py9)s = %(py5)s
{%(py5)s = %(py3)s.read_text
}(errors=%(py7)s)
}path)r   r   r   r   r'   assert %(py11)spy11)r+   r,   r   
api_clientrV   rO   rW   rX   rY   registerr   agent_token_file	read_textstripr1   r8   r/   r0   r2   r3   r4   r5   r   rglobis_file)r   r   rV   rW   rX   rY   respr?   r@   rA   @py_assert7r=   @py_assert12@py_assert11@py_format14@py_format16r:   r;   rR   @py_format9ri   @py_assert0r<   @py_assert8rC   @py_format12s                             r   6test_register_stores_credentials_and_not_install_tokenr}   /   s   		$	$	&#C -MMCc"++V,TU#s4#45tM7JK ##O--O-/O55O57O;OO;OOOOOO7OOOOOOsOOOOsOOO#OOO-OOO/OOO5OOO7OOO;OOOOOOOOO$<(<<$(<<<<<<$(<<<<<<<<<<<<<<<<<<<<<<<<$<<<(<<<<<<<<IOOC(D||~~3///&MdnnMHMnH.MM.MMMMMM.MMMMMMMMMMdMMMMdMMMnMMMHMMM.MMMMMMMMM	 ) 
'	&	&s   LQD(Q
Qc                    SSK Jn   U R                  5       nS H  nX!;   o3(       d  [        R                  " SU4SX!45      S[
        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OSS[
        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OSS.-  nS	S
U0-  n[        [        R                  " U5      5      eS nM     g )Nr   )quick)r\   r   architecture	cpu_countprivate_ipsin)z%(py0)s in %(py2)skeysnapshotrJ   rK   r%   )	discoveryr   collectr1   r8   r/   r0   r2   r3   r4   r5   )r   r   r   r?   rP   rQ   s         r   *test_quick_discovery_returns_expected_keysr   E   s    }}HMssshh Nr   c                    SSK Jn   SnU " U5      nSnUU:H  oD(       d  [        R                  " SU4SUU45      S[        R
                  " 5       ;   d  [        R                  " U 5      (       a  [        R                  " U 5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      S.-  nS	S
U0-  n[        [        R                  " U5      5      eS =n=n=pCSo" U5      nSo2U:H  oD(       d  [        R                  " SU4SX#45      S[        R
                  " 5       ;   d  [        R                  " U 5      (       a  [        R                  " U 5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      S.-  nS	S
U0-  n[        [        R                  " U5      5      eS =n=n=pCg )Nr   )sanitize_remotez*https://user:ghp_secret@github.com/a/b.gitzhttps://github.com/a/b.gitr!   )z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py7)sr   r#   r&   r'   zgit@github.com:a/b.git)
discovery.gitr   r1   r8   r/   r0   r2   r3   r4   r5   )r   r?   r@   r<   rA   rB   rC   s          r   test_git_remote_sanitizationr   M   sv   - EDE'E'	(  E'        D  E  '       4P?34P8PP8PPPPPP4PPPPPP?PPPP?PPP3PPP4PPP8PPPPPPPPr   c                v   SSK Jn  U S-  R                  S5        U S-  R                  S5        U" U 5      S   nSo2U:H  oD(       do  [        R                  " S	U4S
X#45      [        R
                  " U5      [        R
                  " U5      S.-  nSSU0-  n[        [        R                  " U5      5      eS =n=pCg )Nr   )classifyartisan zcomposer.jsonz{}typelaravelr!   )z%(py1)s == %(py4)s)r   r%   zassert %(py6)srN   )discovery.projectsr   
write_textr1   r8   r3   r4   r5   )tmp_pathr   rz   r@   r:   rQ   rR   s          r   test_project_classificationr   W   s    +	%%b)++D1Hf%2222222%222%2222222222r   c                 (   [         R                  " 5        n [        U 5      nSSKJn  SSKJn  U" X" U5      5      n/ nS odULowo(       a  UR                  n	SoU
L onU(       Gd  [        R                  " SU4SXF45      S[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS[        R                  " U5      S.-  nS	S
U0-  oR                  U5        U(       a  [        R                  " SW4SW	W
45      S[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS[        R                  " U	5      [        R                  " U
5      S.-  nSSU0-  oR                  U5        [        R                  " US5      0 -  nSSU0-  n[!        [        R"                  " U5      5      eS =n=n=n=n=n	=pS S S 5        g ! , (       d  f       g = f)Nr   rU   )checkT)is not)z%(py2)s is not %(py5)sinfo)r$   r   z%(py7)sr   is)z;%(py11)s
{%(py11)s = %(py9)s.update_available
} is %(py14)s)r'   rk   py14z%(py16)spy16zassert %(py19)spy19)r+   r,   r   rl   rV   updater   update_availabler1   r8   r/   r0   r2   r3   append_format_boolopr4   r5   )r   r   rV   r   r   r?   r;   r@   rz   @py_assert10@py_assert13ru   rD   rB   @py_format15@py_format17@py_format18@py_format20s                     r   test_update_version_comparisonr   _   s   		$	$	&#C - S.-.A4A4AD$9$9ATAT$AAAAAtAAAAAAtAAAAtAAA4AAAAAAAA$9TAAAAAADAAAADAAA$9AAATAAAAAAAAAAAAAA 
'	&	&s   G$H
Hc                    SSK Jn   U R                  nSo!" U5      nSoCUL oU(       d  [        R                  " SU4SX445      S[
        R                  " 5       ;   d  [        R                  " U 5      (       a  [        R                  " U 5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      [        R                  " U5      S.-  nS	S
U0-  n[        [        R                  " U5      5      eS =n=n=n=pTU R                  nSo!" U5      nSoCUL oU(       d  [        R                  " SU4SX445      S[
        R                  " 5       ;   d  [        R                  " U 5      (       a  [        R                  " U 5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      [        R                  " U5      S.-  nS	S
U0-  n[        [        R                  " U5      5      eS =n=n=n=pTU R                  nSo!" U5      nSoCUL oU(       d  [        R                  " SU4SX445      S[
        R                  " 5       ;   d  [        R                  " U 5      (       a  [        R                  " U 5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      [        R                  " U5      S.-  nS	S
U0-  n[        [        R                  " U5      5      eS =n=n=n=pTU R                  nSo!" U5      nSoCUL oU(       d  [        R                  " SU4SX445      S[
        R                  " 5       ;   d  [        R                  " U 5      (       a  [        R                  " U 5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      [        R                  " U5      S.-  nS	S
U0-  n[        [        R                  " U5      5      eS =n=n=n=pTU R                  nSo!" U5      nSoCUL oU(       d  [        R                  " SU4SX445      S[
        R                  " 5       ;   d  [        R                  " U 5      (       a  [        R                  " U 5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      [        R                  " U5      S.-  nS	S
U0-  n[        [        R                  " U5      5      eS =n=n=n=pTU R                  nSo!" U5      nSoCUL oU(       d  [        R                  " SU4SX445      S[
        R                  " 5       ;   d  [        R                  " U 5      (       a  [        R                  " U 5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      [        R                  " U5      S.-  nS	S
U0-  n[        [        R                  " U5      5      eS =n=n=n=pTU R                  nSo!" U5      nSoCUL oU(       d  [        R                  " SU4SX445      S[
        R                  " 5       ;   d  [        R                  " U 5      (       a  [        R                  " U 5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      [        R                  " U5      S.-  nS	S
U0-  n[        [        R                  " U5      5      eS =n=n=n=pTU R                  nSo!" U5      nSoCUL oU(       d  [        R                  " SU4SX445      S[
        R                  " 5       ;   d  [        R                  " U 5      (       a  [        R                  " U 5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      [        R                  " U5      S.-  nS	S
U0-  n[        [        R                  " U5      5      eS =n=n=n=pTU R                  5        GH  nU R                  o" U5      o(       d  SS[
        R                  " 5       ;   d  [        R                  " U 5      (       a  [        R                  " U 5      OS[        R                  " U5      S[
        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS[        R                  " U	5      S.-  n
[        [        R                  " U
5      5      eS =pGM     g )Nr   )systemz10.0.0.5Tr   )zV%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s._is_private_ipv4
}(%(py4)s)
} is %(py9)sr   )r   r$   r%   rN   r'   rj   rk   z192.168.1.10z
172.16.4.4z	127.0.0.1z169.254.1.1z8.8.8.8Fz
172.32.0.1z	not-an-ipzRassert %(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s._is_private_ipv4
}(%(py3)s)
}ip)r   r$   r   r   )r   r   _is_private_ipv4r1   r8   r/   r0   r2   r3   r4   r5   r   )r   r?   r@   rA   r{   rt   rC   r|   r   r;   rD   s              r   *test_private_ips_excludes_public_addressesr   j   sp    ""6:6":.6$6$66666.666666666666666"666:666.666$6666666"":>:">2:d:d:::::2::::::6::::6:::":::>:::2:::d:::::::""8<8"<08D8D888880888888688886888"888<8880888D8888888""7;7";/747477777/777777677776777"777;777/77747777777""9=9"=19T9T999991999999699996999"999=9991999T9999999""696"9-6666666-666666666666666"6669666-6666666666""9<9"<09E9E999990999999699996999"999<9990999E9999999""8;8";/858588888/888888688886888"888;888/88858888888  "&&*&r*********v****v***&******r****r********** #r   c                    [         R                  " 5        n [        U 5      nSSKJnJnJn  U" U5        U" US5        U" US5        UR                  oUR                  of" 5       ow(       d  SS[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      S.-  n[        [        R                  " U5      5      eS =n=pgUR                  R!                  5       n	SoU	;   o(       d  [        R"                  " SU4S	X45      [        R                  " U
5      S
[        R                  " 5       ;   d  [        R                  " U	5      (       a  [        R                  " U	5      OS
S.-  nSSU0-  n[        [        R                  " U5      5      eS =pSoU	;   o(       d  [        R"                  " SU4S	X45      [        R                  " U
5      S
[        R                  " 5       ;   d  [        R                  " U	5      (       a  [        R                  " U	5      OS
S.-  nSSU0-  n[        [        R                  " U5      5      eS =pUR$                  R                  5       (       Ga  UR$                  R!                  5       nSoU;  o(       d  [        R"                  " SU4SX45      [        R                  " U
5      S[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OSS.-  nSSU0-  n[        [        R                  " U5      5      eS =pSoU;  o(       d  [        R"                  " SU4SX45      [        R                  " U
5      S[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OSS.-  nSSU0-  n[        [        R                  " U5      5      eS =pS S S 5        g ! , (       d  f       g = f)Nr   )rW   save_last_errorsave_statusrevokedzline1
line2zbassert %(py6)s
{%(py6)s = %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.state_file
}.is_file
}()
}r   rM   r   )z%(py1)s in %(py3)s
state_text)r   r   assert %(py5)sr   zline1 line2WOLFPANEL_STATUSrg   )z%(py1)s not in %(py3)s	conf_textWOLFPANEL_LAST_ERROR)r+   r,   r   rO   rW   r   r   
state_filerr   r/   r0   r1   r2   r3   r4   r5   ro   r8   r-   )r   r   rW   r   r   r?   r@   rA   rR   r   rz   r:   @py_format4rD   r   s                  r   ,test_runtime_state_not_written_to_agent_confr   {   sg   		$	$	&#C FFCC#^, ~~'%%'%'''''''''s''''s'''~'''%''''''''''^^--/
&J&&&&&y&&&y&&&&&&J&&&&J&&&&&&&*
*****}***}******
****
*******==  ""//1I%6Y66666%666%666666Y6666Y6666666)::::::):::):::::::::::::::::# 
'	&	&s   P+Q


Qc                 $  ^ [         R                  " 5        n [        U 5      nSSKJnJm  SSKJn  SSKJ	n  U" U5         " U4S jSU5      nU" 5       nU" X5      nSoUL o(       d  [        R                  " SU	4S	Xx45      S
[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS
[        R                  " U5      S.-  n
SSU
0-  n[!        [        R"                  " U5      5      eS =pUR$                  n	SoU:H  o(       d  [        R                  " SU4SX45      S[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS[        R                  " U	5      [        R                  " U5      S.-  nSSU0-  n[!        [        R"                  " U5      5      eS =n	=pUR&                  n	SoU:H  o(       d  [        R                  " SU4SX45      S[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS[        R                  " U	5      [        R                  " U5      S.-  nSSU0-  n[!        [        R"                  " U5      5      eS =n	=pU" X5      nSoUL o(       d  [        R                  " SU	4S	X45      S[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS[        R                  " U5      S.-  n
SSU
0-  n[!        [        R"                  " U5      5      eS =pS S S 5        g ! , (       d  f       g = f)Nr   )	ApiClientApiError)	send_once)rW   c                  "   > \ rS rSrU 4S jrSrg)4test_heartbeat_revoked_on_401.<locals>.Mock401Client   c                   > T" SSS9e)NUnauthorizedi  )status_code )selfpayloadtokenr   s      r   	heartbeat>test_heartbeat_revoked_on_401.<locals>.Mock401Client.heartbeat   s    ~3??r   r   N)__name__
__module____qualname____firstlineno__r   __static_attributes__)r   s   r   Mock401Clientr      s    @ @r   r   Fr   )z%(py0)s is %(py3)ssuccess)r   r   r   r   r   r!   )z.%(py2)s
{%(py2)s = %(py0)s.status
} == %(py5)sr   r)   r*   r   r   )z2%(py2)s
{%(py2)s = %(py0)s.last_error
} == %(py5)ssuccess2)r+   r,   r   rl   r   r   r   r   rO   rW   r1   r8   r/   r0   r2   r3   r4   r5   status
last_error)r   r   r   r   rW   r   clientr   r:   r?   r   rD   r;   r@   rB   r   r   s                   @r   test_heartbeat_revoked_on_401r      s   		$	$	&#C 2'(C	@I 	@ C(%www%zz&Y&Y&&&&&z&&&&&&s&&&&s&&&z&&&Y&&&&&&&~~///////~//////s////s///~////////// S)  5     x      x    x   5       ) 
'	&	&s   M!N
N__main__test_r   zPASS zFAIL )r   r   )0__doc__
__future__r   builtinsr/   _pytest.assertion.rewrite	assertionrewriter1   r   sysr+   pathlibr   ri   insertr   __file__resolveparentsr   rE   rS   r}   r   r   r   r   r   r   r   r   	tracebacksortedglobalsitemsr.   funcsfailuresfunc__code__co_varnamesr,   r   print	Exception	print_excexit)kvs   00r   <module>r      s   #   	 
   3tH~--/77:UBC D',!N,Q3B+";*!0 z!')//"34N441W8MQ4NEH	"T]]666002ccO 32 E$--)*  HH(Q"%  O 32
  	"MHE$--)*!	"s6   9E+E+++FE1%%F1
E?	;F1F76F7