o
    i8                     @   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mZ ddl	Z	ddl
Zddl
mZ ddlZddlZddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZ zddlZdZW n eyg   dZe ZY nw ejjeddZejdddd Z dd Z!dd Z"dd Z#dd Z$dd Z%dd Z&dd Z'd d! Z(d"d# Z)d$d% Z*d&d' Z+d(d) Z,d*d+ Z-d,d- Z.d.d/ Z/d0d1 Z0d2d3 Z1d4d5 Z2d6d7 Z3d8d9 Z4d:d; Z5d<d= Z6d>d? Z7d@dA Z8dBdC Z9dDdE Z:dFdG Z;dHdI Z<dJdK Z=dLdM Z>dNdO Z?dPe@fdQdRZAdPe@fdSdTZBdPe@fdUdVZCdWdX ZDdYdZ ZEd[d\ ZFd]d^ ZGd_d` ZHdadb ZIdcdd ZJdedf ZKdgdh ZLdidj ZMdkdl ZNdmdn ZOdodp ZPdqdr ZQdsdt ZRdudv ZSdwdx ZTdydz ZUd{d| ZVd}d~ ZWdd ZXdd ZYdd ZZdd Z[dd Z\ejjdd Z]ejjdd Z^dd Z_ejjdd Z`ejjdd Zaejjdd Zbejjdd Zcejjdd Zdejjdd Zeejjdd Zfejjdd Zgejjdd Zheejjdd ZidS )z Tests for client initialization.    N)mock)credentials   )_api_client)	_base_url)_replay_api_client)Client)typesFTz(aiohttp is not installed, skipping test.)reason)autousec                   c   s    d V  dt _d S )NF)
api_clienthas_aiohttp r   r   h/home/ubuntu/.local/lib/python3.10/site-packages/google/genai/tests/client/test_client_initialization.pyreset_has_aiohttp2   s   
r   c                 C   \   d}|  d| | jddd t }|jjjrJ |jjj|ks"J t|jjtj	s,J d S )Ngemini_api_keyGEMINI_API_KEYGOOGLE_API_KEYFraising
setenvdelenvr   modelsr   vertexaiapi_key
isinstancer   BaseApiClientmonkeypatchr   clientr   r   r    test_ml_dev_from_gemini_env_only8      r"   c                 C   sZ   d}|  d| |  dd t }|jjjrJ |jjj|ks!J t|jjtjs+J d S )Nr   r   r    )	r   r   r   r   r   r   r   r   r   r   r   r   r   1test_ml_dev_from_gemini_env_with_google_env_emptyD   s   r%   c                 C   r   )Ngoogle_api_keyr   r   Fr   r   r   r   r   r    test_ml_dev_from_google_env_onlyP   r#   r'   c                 C   s|   |j tjdd d}d}| d| | d| t }|jjjr"J |jjj|ks+J t	|jjt
js5J d|jv s<J d S )Ngoogle_genai._api_clientloggerr&   r   r   r   EBoth GOOGLE_API_KEY and GEMINI_API_KEY are set. Using GOOGLE_API_KEY.	set_levelloggingDEBUGr   r   r   r   r   r   r   r   r   textr    caplogr&   r   r!   r   r   r   test_ml_dev_both_env_key_set\   s   r3   c                 C   s<   |j tjdd d}| d| t }|jjjdksJ d S )Nr(   r)   zgemini_api_key
r   r   )r-   r.   r/   r   r   r   r   r   r    r2   r   r!   r   r   r   test_api_key_with_new_linen   s
   r5   c                  C   s2   d} t | d}|jjjrJ |jjj| ksJ d S )Nr&   r   )r   r   r   r   r   )r   r!   r   r   r   test_ml_dev_from_constructorx   s   
r7   c                  C   s(  ddddidd} dddd	id
d}t d| d}|jjjrJ |jj d dks+J |jj d dks7J |jj d d dksEJ |jj d dksQJ t ddd|d}|jjjs`J |jj d dkslJ |jj d dksxJ |jj d d d	ksJ |jj d d
ksJ d S )Nv1main!https://placeholder-fake-url.com/X-Custom-Headercustom_value_mldevi'  )api_versionbase_urlheaderstimeoutv1Bhttps://{self.location}-aiplatform.googleapis.com/{{api_version}}/custom_value_vertexaii*  r&   r   http_optionsr=   r<   r>   r?   Tfake_project_idfake-locationr   projectlocationrD   r   r   r   r   get_read_only_http_optionsmldev_http_optionsvertexai_http_optionsmldev_clientvertexai_clientr   r   r   "test_constructor_with_http_options   sr   	



rQ   c               
   C   s   ddddid} ddddid}zt d| d	}W n! ty9 } zt|ts'J d
t|v s/J W Y d }~nd }~ww zt ddd|d}W d S  tyg } zt|tsTJ dt|v s\J W Y d }~d S d }~ww )Nr@   r9   r:   custom_value)invalid_version_keyr=   r>   rA   )r<   r=   invalid_header_keyr&   rC   rS   TrE   rF   rG   rT   )r   	Exceptionr   
ValueErrorstr)rM   rN   _er   r   r   .test_constructor_with_invalid_http_options_key   s6   
rZ   c                  C   s  t jddddid} t jddddid}td| d}|jjjr!J |jj d	 | jks.J |jj d
 | jks;J |jj d d | j	d ksLJ tddd|d}|jjjs[J |jj d	 |jkshJ |jj d
 |jksuJ |jj d d |j	d ksJ d S )Nr@   r9   r:   rR   )r<   r=   r>   rA   r&   rC   r=   r<   r>   TrE   rF   rG   )
r	   HttpOptionsr   r   r   r   rK   r=   r<   r>   rL   r   r   r   3test_constructor_with_http_options_as_pydantic_type   sf   	



r\   c                 C   h   d}d}|  dd |  d| |  d| t }|jjjs J |jjj|ks)J |jjj|ks2J d S )NrE   rF   GOOGLE_GENAI_USE_VERTEXAI1GOOGLE_CLOUD_PROJECTGOOGLE_CLOUD_LOCATIONr   r   r   r   r   rH   rI   r    
project_idrI   r!   r   r   r   test_vertexai_from_env_11     re   c                 C   r]   )NrE   rF   r^   truer`   ra   rb   rc   r   r   r   test_vertexai_from_env_true?  rf   rh   c                  C   s`   d} d}t d| |d}|jjjsJ |jjj| ksJ |jjj|ks$J t|jjtjs.J d S )NrE   rF   Tr   rH   rI   )	r   r   r   r   rH   rI   r   r   r   )rd   rI   r!   r   r   r   test_vertexai_from_constructorM  s   rj   c                 C   s   t t3 | dd | dd | dd | dd ddd}| tjd| td	d
 W d    d S 1 s;w   Y  d S )Nr`   r$   ra   r   r   c                 S      dS N)NNr   scopesr   r   r   mock_auth_defaultd     zBtest_invalid_vertexai_constructor_empty.<locals>.mock_auth_defaultdefaultTr   N)pytestraisesrV   r   setattrgoogleauthr   )r    ro   r   r   r   'test_invalid_vertexai_constructor_empty]  s   
"ry   c                 C   sp   |  dd |  dd |  dd |  dd ddd}| tjd| td	d
did}|jjjd u s6J d S )Nr`   r$   ra   r   r   c                 S   rk   rl   r   rm   r   r   r   ro   q  rp   zLtest_vertexai_constructor_empty_base_url_override.<locals>.mock_auth_defaultrq   Tr=   zhttps://override.com/r   rD   rs   )r   rv   rw   rx   r   r   r   rI   )r    ro   r!   r   r   r   1test_vertexai_constructor_empty_base_url_overridek  s   
r{   c                 C   sN   t t | dd | dd t  W d    d S 1 s w   Y  d S )Nr   r$   r   )rt   ru   rV   r   r   )r    r   r   r   $test_invalid_mldev_constructor_empty{  s
   "r|   c               
   C   sX   d} d}d}zt d| ||d W d S  ty+ } zt|ts J W Y d }~d S d }~ww )NrE   rF   fake-api_keyT)r   rH   rI   r   r   rU   r   rV   rd   rI   r   rY   r   r   r   "test_invalid_vertexai_constructor1  s   r   c                  C   sJ   t  } d}tt td| |d W d    d S 1 sw   Y  d S )Nr}   T)r   r   r   )r   AnonymousCredentialsrt   ru   rV   r   )credsr   r   r   r   "test_invalid_vertexai_constructor2  s   "r   c                 C   s^   |   !}|jddd d}td|d}|jjjdksJ W d    d S 1 s(w   Y  d S )Nra   Fr   rE   Tr   rH   global)contextr   r   r   r   rI   )r    mrd   r!   r   r   r   (test_vertexai_default_location_to_global  s   
"r   c                 C   s   t  }d}|  /}|jddd |dd td||d}|jjjd	ks(J |jjj	|ks1J W d    d S 1 s<w   Y  d S )
NrE   ra   Fr   r   r$   T)r   r   rH   r   )
r   r   r   r   r   r   r   r   rI   rH   )r    r   rd   r   r!   r   r   r   9test_vertexai_default_location_to_global_with_credentials  s   
"r   c                 C   s   d}d}|   <}|jddd |jddd |d| td|d	}|jjjd
ks,J |jjj|ks5J |jjjr<J W d    d S 1 sGw   Y  d S )Nexplicit_project_idenv_api_keyra   Fr   r`   r   Tr   r   	r   r   r   r   r   r   rI   rH   r   r    rd   r   r   r!   r   r   r   Mtest_vertexai_default_location_to_global_with_explicit_project_and_env_apikey  s   
"r   c                 C   s   d}|   0}|jddd |d| tdddid	}|jjjd
ks%J |jjj|ks.J W d    d S 1 s9w   Y  d S )Nenv_project_idra   Fr   r`   Tr=   zhttps://fake-url.googleapis.comrz   r   r   r   r   r   r   r   rI   rH   r    rd   r   r!   r   r   r   ?test_vertexai_default_location_to_global_with_vertexai_base_url  s   
"r   c                 C   sx   d}|   ,}|jddd |d| tdddid	}|jjjr#J |jjjr*J W d    d S 1 s5w   Y  d S )
Nr   ra   Fr   r`   Tr=   zhttps://fake-url.comrz   r   r   r   r   r   @test_vertexai_default_location_to_global_with_arbitrary_base_url  s   
"r   c                 C   s   d}d}|   :}|jddd |d| |d| tdd	}|jjjd
ks*J |jjj|ks3J |jjjr:J W d    d S 1 sEw   Y  d S )Nr   r   ra   Fr   r`   r   Trr   r   r   r   r   r   r   Htest_vertexai_default_location_to_global_with_env_project_and_env_apikey  s   

"r   c                 C   sv   d}d}|   )}|jddd td||d}|jjj|ks J |jjj|ks)J W d    d S 1 s4w   Y  d S )NrE   zus-central1ra   Fr   Tri   )r   r   r   r   r   rI   rH   r    rd   rI   r   r!   r   r   r   >test_vertexai_no_default_location_when_location_explicitly_set  s   
"r   c                 C   s|   d}d}|   ,}|d| |d| tdd}|jjj|ks#J |jjj|ks,J W d    d S 1 s7w   Y  d S )NrE   zus-west1ra   r`   Trr   )r   r   r   r   r   rI   rH   r   r   r   r   7test_vertexai_no_default_location_when_env_location_set  s   

"r   c                 C   s   d}|   :}|jddd |jddd |dd td|d	}|jjjr(J |jjjr/J |jjj|ks8J W d    d S 1 sCw   Y  d S )
Nvertexai_api_keyra   Fr   r`   r   r$   Tr   r   r   )r    r   r   r!   r   r   r   2test_vertexai_no_default_location_with_apikey_only  s   
"r   c                 C   s   t  }| dd | dd | dd td|d}|jjjs#J |jjjs*J |jjjs1J |jjj	r8J |jjj
|u sAJ t|jjtjsKJ d S )	Nr`   rE   ra   rF   r   r   T)r   r   )r   r   r   r   r   r   r   rH   rI   r   _credentialsr   r   r   )r    r   r!   r   r   r   "test_vertexai_explicit_credentials!  s   r   c                 C   s   d}d}|  dd |  dd |  dd td	||d
}|jjjs$J |jjj|ks-J |jjj|ks6J |jjjr=J t|jjt	j
sGJ d S )Nconstructor_project_idzconstructor-locationr`   r   ra   env_locationr   r$   Tri   r   r   r   r   r   rH   rI   r   r   r   r   rc   r   r   r   &test_vertexai_explicit_arg_precedence14  s   r   c                 C   s   d}|  dd |  dd |  dd td|d}|jjjs!J |jjjr(J |jjjr/J |jjj|ks8J t|jjt	j
sBJ d S )	Nconstructor_apikeyr`   r$   ra   r   r   Tr   r   r   r   r   r   &test_vertexai_explicit_arg_precedence2I  s   r   c               
   C   sV   d} d}d}z
t | ||d W d S  ty* } zt|tsJ W Y d }~d S d }~ww )NrE   rF   r}   )rH   rI   r   r~   r   r   r   r   test_invalid_mldev_constructor\  s   r   c                 C   s|   |j tjdd d}| dd | dd t|d}|jjjr"J |jjj|ks+J t	|jjt
js5J d	|jv s<J d S )
Nr(   r)   constructor_api_keyr   google_env_api_keyr   gemini_env_api_keyr6   r+   r,   r4   r   r   r   "test_mldev_explicit_arg_precedencej  s   
r   
use_vertexc                 C   s   d}|  d| |  dd |rdnd}|  dd|  |  d	d
 t }|jjjr,J |jjj|ks5J t|jjtjs?J d S )Nr&   r   GOOGLE_GENAI_CLIENT_MODEreplayvertexmldevGOOGLE_GENAI_REPLAY_IDtest_replay_id.GOOGLE_GENAI_REPLAYS_DIRECTORYtest_replay_data)	r   r   r   r   r   r   r   replay_api_clientReplayApiClient)r    r   r   api_typer!   r   r   r   "test_replay_client_ml_dev_from_env|  s   
r   c                 C   s   d}d}|  dd |  d| |  d| |  dd |r d	nd
}|  dd|  |  dd t }|jjjs:J |jjj|ksCJ |jjj|ksLJ t|jjtj	sVJ d S )NrE   rF   r^   r_   r`   ra   r   r   r   r   r   r   r   r   )
r   r   r   r   r   rH   rI   r   r   r   )r    r   rd   rI   r   r!   r   r   r   $test_replay_client_vertexai_from_env  s    
r   c                 C   s`   d}|  d| |  dd t }t|jjtjsJ |  dd t }t|jjtjs.J d S )Nr&   r   r   r   r$   )	r   r   r   r   r   r   r   r   r   )r    r   r   client1client2r   r   r    test_change_client_mode_from_env  s   
r   c                 C   s   d}|  dd |  dd t|dd}|jjjsJ |jjjr"J |jjjr)J |jjj|ks2J d|jjj	v s;J t
|jjtjsEJ d S )Nr   ra   r$   r`   T)r   r   
aiplatform)r   r   r   r   r   rH   rI   r   _http_optionsr=   r   r   r   r   r   r   r   %test_vertexai_apikey_from_constructor  s   r   c                 C      d}|  d| | jddd |  dd |  dd td	d
}|jjjs'J |jjj|ks0J |jjjr7J |jjjr>J d|jj	j
v sGJ t|jjtjsQJ d S )Nr   r   r   Fr   ra   r$   r`   Trr   r   r   r   r   r   r   r   r   rH   rI   r   r=   r   r   r   r   r   r   r   1test_vertexai_apikey_from_env_google_api_key_only     
r   c                 C   r   )Nr   r   r   Fr   ra   r$   r`   Trr   r   r   r   r   r   r   1test_vertexai_apikey_from_env_gemini_api_key_only  r   r   c                 C   s   d}|  d| |  dd |  dd |  dd tdd}|jjjs&J |jjj|ks/J |jjjr6J |jjjr=J d	|jjj	v sFJ t
|jjtjsPJ d S )
Nr   r   r   r$   ra   r`   Trr   r   r   r   r   r   r   r   rH   rI   r   r=   r   r   r   r   r   r   r   Ftest_vertexai_apikey_from_env_gemini_api_key_with_google_api_key_empty  s   
r   c                 C   s   |j tjdd d}d}| d| | d| | dd | d	d td
d}|jjjs0J |jjj|ks9J |jjj	r@J |jjj
rGJ d|jjjv sPJ t|jjtjsZJ d|jv saJ d S )Nr(   r)   r&   r   r   r   ra   r$   r`   Trr   r   r+   )r-   r.   r/   r   r   r   r   r   r   rH   rI   r   r=   r   r   r   r0   r1   r   r   r   +test_vertexai_apikey_from_env_both_api_keys  s"   
r   c                  C   sL   d} d}d}t t t| ||dd W d    d S 1 sw   Y  d S )Nr   rE   rF   T)r   rH   rI   r   )rt   ru   rV   r   )r   rd   rI   r   r   r   )test_vertexai_apikey_invalid_constructor1   s   "r   c                 C   s   d}d}d}|  d| |  d| |  dd td|d	}|jjjs%J |jjj|ks.J |jjjr5J |jjjr<J d
|jjj	v sEJ t
|jjtjsOJ d S )Nr   rE   rF   r`   ra   r   r$   Tr   r   r   r    r   rd   rI   r!   r   r   r   test_vertexai_apikey_combo1/  s   r   c                 C   s   d}d}d}|  dd |  dd |  d| td||d	}|jjjs&J |jjjr-J |jjj|ks6J |jjj|ks?J d
|jjj	v sHJ t
|jjtjsRJ d S )Nr   rE   rF   r`   r$   ra   r   Tri   r   r   r   r   r   r   test_vertexai_apikey_combo2C  s   r   c                 C   s   d}d}d}|  d| |  d| |  d| tdd}|jjjs$J |jjjr+J |jjj|ks4J |jjj|ks=J d	|jjj	v sFJ t
|jjtjsPJ d S )
NrE   rF   r   r`   ra   r   Trr   r   r   )r    rd   rI   r   r!   r   r   r   test_vertexai_apikey_combo3W  s   
r   c                 C   s   d}d}|  d| |  d| td|d}|jjjsJ |jjj|ks&J |jjj|ks/J |jjjjdks9J t	|jjt
jsCJ d S )NrE   r   r`   ra   T)r   rI   z"https://aiplatform.googleapis.com/)r   r   r   r   r   rH   rI   r   r=   r   r   r   rc   r   r   r   test_vertexai_global_endpointk  s   
r   c                 C   s`   |j tjdd d}d}d}| d| | d| td|d	}d
|jv s'J d|jv s.J d S )Nr(   r)   rE   rF   r   r`   ra   Tr   INFOz8The user provided Vertex AI API key will take precedence)r-   r.   r/   r   r   r0   )r    r2   rd   rI   r   rX   r   r   r   #test_client_logs_to_logger_instance}  s   r   c                  C   s   t jt \} }| d sJ t| d tjsJ zdd l}t j	t }|d s-J t|d tjs7J W d S  t
yS   |d sFJ t|d tjsPJ Y d S w )Nverifyr   ssl)r   r   _ensure_httpx_ssl_ctxr	   r[   r   r   
SSLContextaiohttp_ensure_aiohttp_ssl_ctxImportError)client_argsasync_client_argsr   r   r   r   /test_client_ssl_context_implicit_initialization  s   r   c                  C   s   t jtjdt tjdd} tjd| id| id}t	j
|\}}|d | ks-J zdd l}t	j
|}|d s>J t|d t jsHJ W d S  tyd   |d sWJ t|d t jsaJ Y d S w NSSL_CERT_FILESSL_CERT_DIRcafilecapathr   )r   r   r   r   r   create_default_contextosenvirongetcertifiwherer	   r[   r   r   r   r   r   r   r   r   ctxoptionsr   r   r   r   r   r   9test_client_ssl_context_explicit_initialization_same_args  s*   

r   c                  C   s   t jtjdt tjdd} t jtjdt tjdd}tjd| id|id}t	j
|\}}|d | ks?J zdd l}t	j
|}|d sPJ t|d t jsZJ W d S  tyv   |d siJ t|d t jssJ Y d S w r   r   )r   	async_ctxr   r   r   r   r   r   r   =test_client_ssl_context_explicit_initialization_separate_args  s2   


r   c                  C      t jtjdt tjdd} tjd| id}t	j
|\}}|d | ks*J zdd l}t	j
|}|d s;J t|d t jsEJ W d S  tya   |d sTJ t|d t js^J Y d S w )Nr   r   r   r   )r   r   r   r   r   r   r   r   9test_client_ssl_context_explicit_initialization_sync_args  &   

r   c                  C   r   )Nr   r   r   r   r   r   r   r   r   r   r   r   :test_client_ssl_context_explicit_initialization_async_args  r   r   c                  C   s|   ddi} ddi}t d| d}|jjjrJ |jj d dks!J t ddd|d	}|jjjs0J |jj d dks<J d S )
Nr=   r9   rA   r&   rC   TrE   rF   rG   rJ   rL   r   r   r   0test_constructor_with_base_url_from_http_options  s0   
r   c                  C   s   t jddd tdd} | jjjrJ | jj d dksJ tddd	d
}|jjjs-J |jj d dks9J t jd d d d S )Nhttps://gemini-base-url.com/https://vertex-base-url.com/
gemini_url
vertex_urlr&   r6   r=   TrE   rF   ri   r=   set_default_base_urlsr   r   r   r   rK   )rO   rP   r   r   r   9test_constructor_with_base_url_from_set_default_base_urls1  s*   

r   c                  C   s   ddi} ddi}t jddd td| d}|jjjrJ |jj d dks(J td	d
d|d}|jjjs7J |jj d dksCJ t jd d d d S )Nr=   (https://gemini-constructor-base-url.com/(https://vertex-constructor-base-url.com/r   r   r   r&   rC   TrE   rF   rG   r   rL   r   r   r   Jtest_constructor_with_constructor_base_url_overrides_set_default_base_urlsL  s8   
r   c                 C   s   |  dd |  dd ddi}ddi}td|d	}|jjjr!J |jj d dks-J td
dd|d}|jjjs<J |jj d dksHJ tjd d d d S )NGOOGLE_GEMINI_BASE_URL https://gemini-env-base-url.com/GOOGLE_VERTEX_BASE_URL https://vertex-env-base-url.com/r=   r   r   r&   rC   TrE   rF   rG   r   )r   r   r   r   r   rK   r=   r   )r    rM   rN   rO   rP   r   r   r   Jtest_constructor_with_constructor_base_url_overrides_environment_variablesq  s<   
r   c                 C   s   |  dd |  dd tjddd tdd	}|jjjrJ |jj d
 dks+J tdddd}|jjjs9J |jj d
 dksEJ tjd d d d S )Nr   r   r   r   r   r   r   r&   r6   r=   TrE   rF   ri   )r   r=   r   r   r   r   r   rK   r    rO   rP   r   r   r   Ytest_constructor_with_base_url_from_set_default_base_urls_overrides_environment_variables  s6   

r   c                 C   s   |  dd |  dd tdd}|jjjrJ |jj d dks$J tdd	d
d}|jjjs2J |jj d dks>J d S )Nr   r   r   r   r&   r6   r=   TrE   rF   ri   )r   r   r   r   r   rK   r   r   r   r   9test_constructor_with_base_url_from_environment_variables  s$   

r  c                  C   s:   t dddd} dt_| j rJ dt_| j sJ d S )NTrE   rF   ri   F)r   r   r   r   _use_aiohttpr!   r   r   r   6test_async_transport_absence_allows_aiohttp_to_be_used  s   r  c                  C   sD   t dddtji dd} dt_| j rJ dt_| j s J d S )NTrE   rF   r   rG   F)r   r	   r[   r   r   r   r  r  r   r   r   Htest_async_async_client_args_without_transport_allows_aiohttp_to_be_used  s   
r  c                  C   sL   t dddtjdt idd} dt_| j rJ dt_| j r$J d S )NTrE   rF   	transportr   rG   F)	r   r	   r[   httpxAsyncBaseTransportr   r   r   r  r  r   r   r   Dtest_async_transport_forces_httpx_regardless_of_aiohttp_availability  s   
	r	  c                     sD   t dddd} | j I dH }t|tjsJ | jj|u s J dS )z8Tests that _get_async_auth_lock returns an asyncio.Lock.TrE   rF   ri   N)r   r   _get_async_auth_lockr   asyncioLock_async_auth_lockr!   lockr   r   r   ,test_get_async_auth_lock_basic_functionality  s   r  c                     sl   t dddd} | j I dH }| j I dH }| j I dH }||u s&J ||u s,J t|tjs4J dS )z8Tests that multiple calls return the same lock instance.TrE   rF   ri   N)r   r   r
  r   r  r  )r!   lock1lock2lock3r   r   r   .test_get_async_auth_lock_returns_same_instance  s   r  c                    s  | j ddd tjtjdd_d_d_tjdfd}| t	j
d	| fd
d}tj|d}|_tjdi dd}tj|d}| tjd| tdddd d j_tjjdd& fddtdD }tj|D ]}| jdks|J qqW d   n1 sw   Y  |  |  |jdksJ d_tjjdd& fddtdD }tj|D ]}| jdksJ qW d   n1 sw   Y  |  |  |jdksJ dS )z1Tests that synchronous API calls are thread-safe.r   Fr   specinitial-tokenNtest-projectreturn_valuerq   c                       d _ d _d S Nrefreshed-tokenFtokenexpiredrequest
mock_credsr   r   refresh_side_effect/     
zCtest_threaded_generate_content_locking.<locals>.refresh_side_effectside_effect   z@{"candidates": [{"content": {"parts": [{"text": "response"}]}}]})status_coder>   r0   r"  TrE   rF   ri   r   )max_workersc                    $   g | ]}j  jjd t|dqS z
gemini-pro)modelcontentssubmitr   generate_contentrW   .0ir!   executorr   r   
<listcomp>G      z:test_threaded_generate_content_locking.<locals>.<listcomp>
   responsec                    r,  r-  r0  r3  r6  r   r   r8  W  r9     )r   r   Mockr   Credentialsr  r   quota_project_idrv   rw   rx   refreshr  Responser   SyncHttpxClientr   r   r   
concurrentfuturesThreadPoolExecutorrangeas_completedresultr0   assert_called_onceassert_not_called
call_count)r    ro   r%  mock_refreshmock_httpx_responsemock_requestrD  futurer   )r!   r7  r$  r   &test_threaded_generate_content_locking!  sX   

rP  c                    s  t jtjd d _d _d _t j dfd}| tj	d|  fdd	}t j|d
}| _
tdddd}d|j_t|j |j |j I dH }|g dksVJ |  |  d _t|j |j |j I dH }|g dks|J |  |  dS )zETests that _async_access_token uses locks to prevent race conditions.r  r  FNr  r  rq   c                    r  r  r  r!  r#  r   r   r%  s  r&  z<test_async_access_token_locking.<locals>.refresh_side_effectr'  TrE   rF   ri   )r  r  r  )r  r  r  )r   r=  r   r>  r  r   r?  rv   rw   rx   r@  r   r   r   r  gather_async_access_tokenrI  rJ  )r    ro   r%  rL  r!   tokensr   r#  r   test_async_access_token_lockinge  s>   

rT  c                     s   t dddd dtf fddfdd	td
D } tj|  I dH }dd	 |D tfddD s:J ddd	 |D }t|ttd
ksOJ ddS )zDTests that concurrent access to _get_async_auth_lock is thread-safe.TrE   rF   ri   task_idc                        j  I d H }| t|fS rs   r   r
  id)rU  r  r  r   r   get_lock_task     zAtest_get_async_auth_lock_concurrent_access.<locals>.get_lock_taskc                       g | ]} |qS r   r   r3  )rY  r   r   r8        z>test_get_async_auth_lock_concurrent_access.<locals>.<listcomp>r<  Nc                 S      g | ]}|d  qS    r   r4  rH  r   r   r   r8    r\  c                 3       | ]	}| d  kV  qdS r   Nr   r4  lock_idlock_idsr   r   	<genexpr>      
z=test_get_async_auth_lock_concurrent_access.<locals>.<genexpr>z+All tasks should get the same lock instancec                 S   r]  r   r   r`  r   r   r   r8    r\  zAll tasks should complete)r   intrF  r  rQ  allsortedlist)tasksresultstask_idsr   )r!   rY  rf  r   *test_get_async_auth_lock_concurrent_access  s   
 rq  c                     s  t dddd g dtffddt  }  fdd	td
D }fdd	tdD }ttj| tj| I dH \}}t  }||  }t|d
ksTJ dt|dks^J dtdkshJ ddd	 |D tfddD s|J |dk sJ d|dddS )zNTests that _get_async_auth_lock doesn't interfere with other async operations.TrE   rF   ri   op_idc                    s&   t dI d H   |  d|  S )Ng{Gz?
operation_)r  sleepappend)rr  )completed_operationsr   r   mock_async_operation  s   

zTtest_get_async_auth_lock_doesnt_block_other_operations.<locals>.mock_async_operationc                       g | ]} j  qS r   r   r
  r4  rX   r  r   r   r8        zJtest_get_async_auth_lock_doesnt_block_other_operations.<locals>.<listcomp>r:  c                    r[  r   r   r3  )rw  r   r   r8    r\     Nz&All auth lock requests should completezAll work tasks should completez$All async operations should completec                 S   s   g | ]}t |qS r   )rX  r4  r  r   r   r   r8    r\  c                 3   ra  rb  r   rc  re  r   r   rg        zItest_get_async_auth_lock_doesnt_block_other_operations.<locals>.<genexpr>皙?zOperations took too long (.3fz s), suggesting blocking occurred)	r   rj  r  get_event_looptimerF  rQ  lenrk  )
start_time
auth_tasks
work_tasksauth_resultswork_resultsend_time
total_timer   )r!   rv  rf  rw  r   6test_get_async_auth_lock_doesnt_block_other_operations  s,   
r  c                     s   t dddd} | jjdu sJ | jjdu sJ | j I dH }| jjdus(J | jjdus0J t|tjs8J | jj}||usBJ t|tjsJJ | j I dH }||u sXJ | jj|u s`J dS )z.Tests the creation lock lifecycle and cleanup.TrE   rF   ri   N)r   r   r  _async_auth_lock_creation_lockr
  r   r  r  )r!   r  creation_lockr  r   r   r   0test_get_async_auth_lock_creation_lock_lifecycle  s    r  c                     s  t dddd d} dtf fddt  }fd	d
t| D }tj| I dH }t  | }dd
 |D }dd
 |D dd
 |D }t|| ksQJ t|t	t| ks]J t
fddD slJ dt|}|dk s}J d|dd|dk sJ d|dddS )z7Tests _get_async_auth_lock under heavy concurrent load.TrE   rF   ri   d   call_idc                    s<   t   } j I d H }t   }| t||| fS rs   )r  r  r  r   r
  rX  )r  startr  endr  r   r   get_lock_with_timing  s
   zAtest_get_async_auth_lock_under_load.<locals>.get_lock_with_timingc                    r[  r   r   r3  )r  r   r   r8    r\  z7test_get_async_auth_lock_under_load.<locals>.<listcomp>Nc                 S   r]  ri  r   r4  rr   r   r   r8    r\  c                 S   r]  r^  r   r  r   r   r   r8    r\  c                 S   r]  )   r   r  r   r   r   r8    r\  c                 3   ra  rb  r   rc  re  r   r   rg    rh  z6test_get_async_auth_lock_under_load.<locals>.<genexpr>zAll calls should get same lockg      ?zTotal time (r  zs) suggests blockingr  zMax individual call time (zs) too high)r   rj  r  r  r  rF  rQ  r  rl  rm  rk  max)num_concurrent_callsr  rn  ro  r  call_ids
call_timesmax_call_timer   )r!   r  rf  r   #test_get_async_auth_lock_under_load  s2   

r  c                     s  t ddddtjtjd} d| _d| _d| _| j_	d	t
ffd
d dt
ffdd fddtdD }fddtdD }ttj| tj| I dH \}}t|dks]J t|dkseJ dd |D tfddD syJ tdd |D sJ dS )zITests _get_async_auth_lock working correctly with actual auth operations.TrE   rF   ri   r  z
test-tokenFNrr  c              	      sh    j  I d H }|4 I d H  tdI d H  d|  W  d   I d H  S 1 I d H s-w   Y  d S )NMbP?auth_op_)r   r
  r  rt  )rr  r  r  r   r   auth_operation6  s   0zQtest_get_async_auth_lock_interleaved_with_auth_operations.<locals>.auth_operationreq_idc                    rV  rs   rW  )r  r  r  r   r   lock_request=  rZ  zOtest_get_async_auth_lock_interleaved_with_auth_operations.<locals>.lock_requestc                    r[  r   r   r3  )r  r   r   r8  B  r\  zMtest_get_async_auth_lock_interleaved_with_auth_operations.<locals>.<listcomp>r:  c                    r[  r   r   r3  )r  r   r   r8  C  r\  c                 S   r]  r^  r   r`  r   r   r   r8  N  r\  c                 3   ra  rb  r   rc  re  r   r   rg  O  r~  zLtest_get_async_auth_lock_interleaved_with_auth_operations.<locals>.<genexpr>c                 s   s    | ]}| d V  qdS )r  N)
startswithr`  r   r   r   rg  R  s    )r   r   r=  r   r>  r  r   r?  r   r   rj  rF  r  rQ  r  rk  )r$  r  
lock_tasksr  lock_resultsr   )r  r!   rf  r  r   9test_get_async_auth_lock_interleaved_with_auth_operations'  s*   r  c                     sn   dd } |  I dH \} |j  I dH } |u sJ t tjs#J  fdd}| I dH }|dks5J dS )zHTests that _get_async_auth_lock works correctly with event loop context.c                     s(   t dddd} | j I d H }| |fS )NTrE   rF   ri   )r   r   r
  r  r   r   r   create_client_and_get_lockY  s   zStest_get_async_auth_lock_with_event_loop_switch.<locals>.create_client_and_get_lockNc                	      sR    4 I d H  t dI d H  	 W d   I d H  dS 1 I d H s"w   Y  d S )Nr  success)r  rt  r   r  r   r   test_lock_functionalityj  s
   0zPtest_get_async_auth_lock_with_event_loop_switch.<locals>.test_lock_functionalityr  )r   r
  r   r  r  )r  r!   r  r  rH  r   r  r   /test_get_async_auth_lock_with_event_loop_switchU  s   r  c                     s   t dddd tjjdgfdd} | tj_z7 fdd	td
D }tj| I dH tfddD s;J d dksKJ dd  dW tj_dS tj_w )z8Tests the double-checked locking pattern implementation.TrE   rF   ri   r   c                    s    d  d7  < | S )Nr   r_  r   )self)lock_creation_countoriginal_lock_initr   r   counting_lock_init}  s   zKtest_get_async_auth_lock_double_checked_locking.<locals>.counting_lock_initc                    rx  r   ry  rz  r  r   r   r8    r{  zCtest_get_async_auth_lock_double_checked_locking.<locals>.<listcomp>2   Nc                 3   s    | ]	}| d  u V  qdS rb  r   r}  )locksr   r   rg    r~  zBtest_get_async_auth_lock_double_checked_locking.<locals>.<genexpr>   zCreated z locks, expected ~2)r   r  r  __init__rF  rQ  rk  )r  rn  r   )r!   r  r  r  r   /test_get_async_auth_lock_double_checked_lockings  s    r  c                     s   t dddd} | j I dH }| jj}tdD ]}| j I dH }||u s(J | jj|u s0J q| j I dH }| jj}||u sCJ ||u sIJ dS )zGTests that _get_async_auth_lock doesn't leak memory under repeated use.TrE   rF   ri   Nr  )r   r   r
  r  rF  )r!   initial_lockinitial_creation_lockrX   r  
final_lockfinal_creation_lockr   r   r   *test_get_async_auth_lock_memory_efficiency  s    
r  c                     sR   t dddd} dt_| j I dH }|dusJ | j I dH }||u s'J dS )zJTests that _get_async_auth_lock works correctly with aiohttp session lock.TrE   rF   ri   N)r   r   r   r   _get_aiohttp_session)r!   initial_sessionsessionr   r   r   test_get_aiohttp_session  s   r  )j__doc__r  concurrent.futuresrC  r.   r   r   unittestr   r   google.authrw   r   r  rt   r$   r   r   r   r=   r   r   r   r	   r   AIOHTTP_NOT_INSTALLEDr   	MagicMockmarkskipifrequires_aiohttpfixturer   r"   r%   r'   r3   r5   r7   rQ   rZ   r\   re   rh   rj   ry   r{   r|   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   boolr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r	  r  r  rP  rT  rq  r  r  r  r  r  r  r  r  r   r   r   r   <module>   s   


	K$A	 "%*$

D
7

+

'
-

"
