
    ^                        S r SSKJr  SSKJr  SSKJr  SSKrSSKrSSKrSSKrSSK	r	SSK
r
SSKJr  SSKJr  SSKJr  SS	KJr  SSKJr  SS
KJr  SSKrS r\R.                  " S\
R0                  5      r\R.                  " S\
R0                  5      r\R6                  " SSS9r\R6                  " SSSS9r/ SQrSS/rS r S r!S r"S r#S r$S r%S r&S r'S r(S r)S r*S  r+S! r,S" r-S# r.S$ r/0 S%\,_S&\-_S'\"_S(\"_S)\._S*\/_S+\ _S,\ _S-\._S.\*_S/\ _S0\(_S1\+_S2\&_S3\%_S4\ _S5\"_\ \.\"\"\"\.\ \'\ \#\$\"S6.Er0S7 r1S8 r2S9 r3S: r4S; r5S< r6S= r7\Rp                  " S>5      r9S? r:S@ r;\Rp                  " SA5      r<SB r=\Rp                  " SC5      r>SD r?\Rp                  " SE5      r@\Rp                  " SF5      rASG rBSH rCSI rD\Rp                  " SJ5      rESK rFg)Lz?A shared library to validate 'gcloud test' CLI argument values.    )absolute_import)division)unicode_literalsN)
exceptions)util)storage_util)arg_parsers)filesc                 ~    Uc  [         R                  " U S5      eU [        ;   a  [        U    " X5      $ [        X5      $ )a  Do checks/mutations on arg values parsed from YAML which need validation.

Any arg not appearing in the _FILE_ARG_VALIDATORS dictionary is assumed to be
a simple string to be validated by the default _ValidateString() function.

Mutations of the args are done in limited cases to improve ease-of-use.
This includes:
1) The YAML parser automatically converts attribute values into numeric types
where possible. The os-version-ids for Android devices happen to be integers,
but the Testing service expects them to be strings, so we automatically
convert them to strings so users don't have to quote each one.
2) The include: keyword, plus all test args that normally expect lists (e.g.
device-ids, os-version-ids, locales, orientations...), will also accept a
single value which is not specified using YAML list notation (e.g not enclosed
in []). Such single values are automatically converted into a list containing
one element.

Args:
  arg_internal_name: the internal form of the arg name.
  arg_value: the argument's value as parsed from the yaml file.

Returns:
  The validated argument value.

Raises:
  InvalidArgException: If the arg value is missing or is not valid.
zno argument value found.)test_exceptionsInvalidArgException_FILE_ARG_VALIDATORS_ValidateStringarg_internal_name	arg_values     8lib/googlecloudsdk/api_lib/firebase/test/arg_validate.pyValidateArgFromFiler   &   sL    8 

-
-.?.HJ J.. 123DPP	*	66       1m6h)lower_boundupper_boundus)r   r   parsed_unit)portrait	landscapedefaultallnonec                     [        U[        R                  5      (       a  U/$ [        U[        5      (       a  [	        U5      /$ [        U[
        5      (       a  U Vs/ s H  n[        X5      PM     sn$ [        R                  " X5      es  snf )a  Validates an arg whose value should be a list of strings.

Args:
  arg_internal_name: the internal form of the arg name.
  arg_value: the argument's value parsed from yaml file.

Returns:
  The validated argument value.

Raises:
  InvalidArgException: the argument's value is not valid.
)	
isinstancesixstring_typesintstrlistr   r   r   )r   r   values      r   ValidateStringListr*   T   sy     	3++,,;	3	N	4  CLM9%O-59MM++,=II Ns   Bc                     [        U[        R                  5      (       a  U$ [        U[        5      (       a  [	        U5      $ [
        R                  " X5      e)z7Validates an arg whose value should be a simple string.)r#   r$   r%   r&   r'   r   r   r   s     r   r   r   k   sD    	3++,,	3y>++,=IIr   c                 \    [        U[        5      (       a  U$ [        R                  " X5      e)z8Validates an argument which should have a boolean value.)r#   boolr   r   r   s     r   _ValidateBoolr.   t   s)     	4  ++,=IIr   c                 f    [        U[        R                  5      (       a  [        U5      $ [        U[        5      (       a  [        [        U5      5      $  [        R                  " X5      e! [        R                   a0  n[        R                  " U [        R                  " U5      5      eSnAff = f)z9Validates an argument which should have a Duration value.N)r#   r$   r%   TIMEOUT_PARSERr&   r'   r	   ArgumentTypeErrorr   r   	text_typer   r   es      r   _ValidateDurationr5   }   s    @)S--..I&&	Is	#	#C	N++ 
$
 	++,=II 
	&	& @

-
-.?.1mmA.>@ @@   )A, (A, ,B0 +B++B0c                 f    [        U[        R                  5      (       a  [        U5      $ [        U[        5      (       a  [        [        U5      5      $  [        R                  " X5      e! [        R                   a0  n[        R                  " U [        R                  " U5      5      eSnAff = f)zGValidates an argument which should have Duration value in microseconds.N)r#   r$   r%   TIMEOUT_PARSER_USr&   r'   r	   r1   r   r   r2   r3   s      r   _ValidateDurationUsr9      s    @)S--..y))	Is	#	#s9~.. 
$
 	++,=II 
	&	& @

-
-.?.1mmA.>@ @@r6   c                     [        U[        5      (       a  [        [        U5      5      $  [        R                  " X5      e! [        R
                   a0  n[        R                  " U [        R                  " U5      5      eSnAff = f)z5Validates an argument which should be an integer > 0.N)
r#   r&   POSITIVE_INT_PARSERr'   r	   r1   r   r   r$   r2   r3   s      r   _ValidatePositiveIntegerr<      s{    @)S!! Y00 "
 	++,=II 
	&	& @

-
-.?.1mmA.>@ @@   (A B+BBc                     [        U[        5      (       a  [        [        U5      5      $  [        R                  " X5      e! [        R
                   a0  n[        R                  " U [        R                  " U5      5      eSnAff = f)z6Validates an argument which should be an integer >= 0.N)
r#   r&   NONNEGATIVE_INT_PARSERr'   r	   r1   r   r   r$   r2   r3   s      r   _ValidateNonNegativeIntegerr@      s{    @)S!!#C	N33 "
 	++,=II 
	&	& @

-
-.?.1mmA.>@ @@r=   c                     [        U[        5      (       a  U/n[        U[        5      (       a  U Vs/ s H  n[        X5      PM     sn$ [        R
                  " X5      es  snf )a   Validates an arg whose value should be a list of ints > 0.

Args:
  arg_internal_name: the internal form of the arg name.
  arg_value: the argument's value parsed from yaml file.

Returns:
  The validated argument value.

Raises:
  InvalidArgException: the argument's value is not valid.
)r#   r&   r(   r<   r   r   )r   r   vs      r   _ValidatePositiveIntListrC      sY     	3I	4  DMNIq$%6:INN++,=II Os   A c                     [        X5      nU H  n[        U5        M     [        U5      [        [        U5      5      :w  a  [        R
                  " U S5      eU$ )z=Validates that 'orientations' only contains allowable values.z!orientations may not be repeated.)r*   _ValidateOrientationlensetr   r   )r   r   orientations      r   _ValidateOrientationListrI      sU     !2>)k% ^s3y>**

-
->@ @	r   c                 D    U [         ;  a  [        R                  " U 5      eg )N)ORIENTATION_LISTr   OrientationNotFoundError)rH   s    r   rE   rE      s!    ((

2
2;
?? )r   c                 H    U[         ;  a  [        R                  " U S5      eU$ )Nz=Invalid permissions specified. Must be either "all" or "none")PERMISSIONS_LISTr   r   r   s     r   _ValidatePermissionsrO      s.    &&

-
-GI I 
r   c                 h    [        X5      n[        U5      S:  a  [        R                  " U S5      eU$ )z6Validates that 'obb-files' contains at most 2 entries.   z'At most two OBB files may be specified.r*   rF   r   r   r   s     r   _ValidateObbFileListrS      s:     !2>)^a

-
-DF F	r   c                     [        X5      n[        U5      S:  a  [        R                  " U S5      e[        U5      S:  a  [        R                  " U S5      eU$ )z;Validates that 'additional-apks' contains [1, 100] entries.r   z,At least 1 additional apk must be specified.d   z-At most 100 additional apks may be specified.rR   r   s     r   _ValidateAdditionalApksListrV      sa     !2>)^a

-
-IK K^c

-
-JL L	r   c                     [        U5      S:  a  [        R                  " U S5      e[        U5      S:  a  [        R                  " U S5      eU$ )z;Validates that 'additional-ipas' contains [1, 100] entries.r   z,At least 1 additional ipa must be specified.rU   z-At most 100 additional ipas may be specified.)rF   r   r   r   s     r   _ValidateAdditionalIpasListrX      sV    ^a

-
-IK K^c

-
-JL L	r   c                     [        U[        5      (       a4  0 nUR                  5        H  u  p4[        X5      U[	        U5      '   M     U$ [
        R                  " U S5      e)zDValidates that an argument is a dict of string-type key-value pairs.zMalformed key-value pairs.)r#   dictitemsr   r'   r   r   )r   r   new_dictkeyr)   s        r   _ValidateKeyValueStringPairsr^      s[    	4  H!)*+<Dhs3x *O

-
-.?.JL Lr   c                 R   [        U[        5      (       d  [        R                  " U S5      e/ nU Hr  n[        U[        5      (       d  [        R                  " U S5      e0 nUR                  5        H  u  pV[        XV5      U[        U5      '   M     UR                  U5        Mt     U$ )zHValidates that an argument is a list of dicts of key=value string pairs.z)is not a list of maps of key-value pairs.z7Each list item must be a map of key-value string pairs.)	r#   r(   r   r   rZ   r[   r   r'   append)r   r   new_lista_dictr\   r]   r)   s          r   "_ValidateListOfStringToStringDictsrc     s    	It	$	$

-
-FH H(ffd##//

CE E H*36hs3x 'OOH  
/r   additional_apksadditional_ipasasync_auto_google_loginclient_detailsdevice
device_idsdirectories_to_pullenvironment_variablesgrant_permissionslocalesorientations	obb_filesnum_flaky_test_attemptsnum_uniform_shardstest_targets_for_shardtest_special_entitlements)os_version_idsother_filesperformance_metricsrecord_videoresignrobo_directivesscenario_labelsscenario_numberstest_targetstimeout
timeout_ususe_orchestratorc                 4    U S:X  a  gU R                  SS5      $ )zFConverts a user-visible arg name into its corresponding internal name.asyncrf   -_)replace)arg_external_names    r   InternalArgNameFromr   ;  s"    '! 		"	"3	,,r   c                    X!   S   US   -   nX!   S   US   -   nXV-   nU H=  n[        XS5      c  M  X;  d  M  [        R                  " USR                  U5      5      e   U HY  n[        XS5      b  M  [        R
                  " SR                  [        R                  " U5      5      SR                  U5      5      e   g)a<  Raise errors if required args are missing or invalid args are present.

Args:
  args: an argparse.Namespace object which contains attributes for all the
    arguments that were provided to the command invocation (i.e. command
    group and command arguments combined).
  test_type: string containing the type of test to run.
  type_rules: a nested dictionary defining the required and optional args
    per type of test, plus any default values.
  shared_rules: a nested dictionary defining the required and optional args
    shared among all test types, plus any default values.
  all_test_args_set: a set of strings for every gcloud-test argument to use
    for validation.

Raises:
  InvalidArgException: If an arg doesn't pair with the test type.
  RequiredArgumentException: If a required arg for the test type is missing.
requiredoptionalNz%may not be used with test type [{0}].z{0}z'must be specified with test type [{0}].)getattrr   r   formatr   RequiredArgumentExceptionExternalArgNameFrom)	args	test_type
type_rulesshared_rulesall_test_args_setrequired_argsoptional_argsallowable_args_for_typeargs	            r   ValidateArgsForTestTyper   J  s    ( '
3l:6NN-'
3l:6NN-)9 ct$+		+118??	JL 	L  ct$'00
,,::3?
@
3
:
:9
EG G r   c                    U R                   c  g [        R                  R                  U R                   SS9nUR                  U l         g! [         a0  n[
        R                  " S[        R                  " U5      5      eSnAff = f)zDo some basic sanity checks on the format of the results-bucket arg.

Args:
  args: the argparse.Namespace containing all the args for the command.

Raises:
  InvalidArgumentException: the bucket name is not valid or includes objects.
NF)require_prefixzresults-bucket)
results_bucketr   BucketReferenceFromArgument	Exceptionr   InvalidArgumentExceptionr$   r2   bucket)r   
bucket_referrs      r   ValidateResultsBucketr   p  s     
 
B--::4;N;NJO ; QJ
 #))$ 
 B

-
-.>.1mmC.@B BBs   (A
 

B+A??Bc                 T   U R                   (       d  [        5       U l         gU R                   R                  S5      U l         SU R                   ;   d  SU R                   ;   a  [        R                  " SS5      e[        U R                   5      S:  a  [        R                  " SS5      eg)	zSanity checks the results-dir arg and apply a default value if needed.

Args:
  args: the argparse.Namespace containing all the args for the command.

Raises:
  InvalidArgumentException: the arg value is not a valid cloud storage name.
N/
zresults-dirz3Name may not contain newline or linefeed charactersi   zName is too long)results_dir_GenerateUniqueGcsObjectNamerstripr   r   rF   )r   s    r   ValidateResultsDirr     s     
		35D
%%,,S1$	T)9)9!9

-
-LN N 			S 

-
-m=O
PP !r   c            	         SR                  [        R                  R                  5       R                  [        R
                  (       a  SOS5      SR                  [        R                  " [        R                  S5      5      5      $ )a  Create a unique GCS object name to hold test results in the results bucket.

The Testing back-end needs a unique GCS object name within the results bucket
to prevent race conditions while processing test results. By default, the
gcloud client uses the current time down to the microsecond in ISO format plus
a random 4-letter suffix. The format is: "YYYY-MM-DD_hh:mm:ss.ssssss_rrrr".

Returns:
  A string with the unique GCS object name.
z{0}_{1}   _r       )r   datetimenow	isoformatr$   PY2joinrandomsamplestringascii_letters r   r   r   r     s\     
		''SA277
--,,a
0D2
3 3r   c                     U R                   (       d  g[        5       nU R                    H&  nUR                  SU5      nUR                  U5        M(     [	        U5      U l         g)a  Validate os-version-ids strings against the TestEnvironmentCatalog.

Also allow users to alternatively specify OS version strings (e.g. '5.1.x')
but translate them here to their corresponding version IDs (e.g. '22').
The final list of validated version IDs is sorted in ascending order.

Args:
  args: an argparse namespace. All the arguments that were provided to the
    command invocation (i.e. group and command arguments combined).
  catalog_mgr: an AndroidCatalogManager object for working with the Android
    TestEnvironmentCatalog.
Nversion)ru   rG   ValidateDimensionAndValueaddsorted)r   catalog_mgrvalidated_versionsvers
version_ids        r   ValidateOsVersionsr     sX     
		
u!!d66y$GJ:& " 12$r   c                 ^    U R                   (       a  UR                  U R                   5        gg)zEValidates an Xcode version string against the TestEnvironmentCatalog.N)xcode_versionValidateXcodeVersion)r   r   s     r   r   r     s$    	$$T%7%78 r   z2(.*[\\/:])?(main|patch)\.\d+(\.[a-zA-Z]\w*)+\.obb$c                 n   U (       aW  U  Vs/ s HF  nU(       a$  UR                  [        R                  5      (       a  UO[        R                  " U5      PMH     snU SS& U =(       d    /  HC  n[
        R                  U5      (       a  M  [        R                  " SSR                  U5      5      e   gs  snf )zConfirm that any OBB file names follow the required Android pattern.

Also expand local paths with "~"

Args:
  obb_files: list of obb file references. Each one is either a filename on the
    local FS or a gs:// reference.
Nrp   zm[{0}] is not a valid OBB file name, which must have the format: (main|patch).<versionCode>.<package.name>.obb)

startswithr   GSUTIL_BUCKET_PREFIXr
   ExpandHomeDir_OBB_FILE_REGEXmatchr   r   r   )rp   obb_files     r    NormalizeAndValidateObbFileNamesr     s      7@ 7@( !L==>> 	H%	&6?IaL
 ??h  **//
::@&:JL L #s   AB2c                 J   [        5       n[        5       n[        R                  " U R                  =(       d    0 5       H  u  p4[        R
                  " U5      u  pVUS;   a-  U(       a&  [        R                  " SSR                  X45      5      eU(       d&  [        R                  " SSR                  U5      5      eXa;   a  UR                  U5        M  UR                  U5        M     U(       a5  [        R                  " SSR                  SR                  U5      5      5      eg)z5Validates key-value pairs for 'robo_directives' flag.)clickignorerz   z>Input value not allowed for click or ignore actions: [{0}={1}]z$Missing resource_name for key [{0}].z0Duplicate resource names are not allowed: [{0}].z, N)rG   r$   	iteritemsrz   r   ParseRoboDirectiveKeyr   r   r   r   r   )r   resource_names
duplicatesr]   r)   action_typeresource_names          r   ValidateRoboDirectivesListr     s    5.u*MM4#7#7#=2?jc#'#=#=c#B [))e//

J6#  //
CJJ3OQ Q &nn]#'# @& 

-
-:AAIIj!	#$ $ r   z^[a-zA-Z][\w.-]+$c                     U R                   =(       d    /  HC  n[        R                  U5      (       a  M  [        R                  " SSR                  U5      5      e   g)z;Validates key-value pairs for 'environment-variables' flag.rl   z"Invalid environment variable [{0}]N)rl   _ENVIRONMENT_VARIABLE_REGEXr   r   r   r   )r   r]   s     r    ValidateEnvironmentVariablesListr     sO    ((.B.c&,,S11//
!
.
5
5c
:< < /r   z1^/?/(?:sdcard|data/local/tmp)(?:/[\w\-\.\+ /]+)*$c                 $   U (       a2  U  Vs/ s H!  o(       a  [         R                  " U5      OUPM#     snU SS& U =(       d    /  HC  n[        R                  U5      (       a  M  [        R
                  " SSR                  U5      5      e   gs  snf )zValidate list of file paths for 'directories-to-pull' flag.

Also collapse paths to remove "." ".." and "//".

Args:
  dirs: list of directory names to pull from the device.
Nrk   Invalid path [{0}])	posixpathabspath_DIRECTORIES_TO_PULL_PATH_REGEXr   r   r   r   )dirspath	file_paths      r   )NormalizeAndValidateDirectoriesToPullListr     s~     
EIJTT$y  &D8TJDGJBJi*00;;//
!5!<!<Y!GI I  Ks   (Bz.*,(|\s+)(package |class ).*z
.*,(\s+).*c                 P   [        U S0 5      (       d  gU R                   H  n[        R                  U5      (       a&  [        R
                  " SSR                  U5      5      e[        R                  U5      (       d  M_  [        R
                  " SSR                  U5      5      e   g)z9Validates --test-targets-for-shard uses proper delimiter.rs   Nz[{0}] is not a valid test_targets_for_shard argument. Multiple "package" and "class" specifications should be separated by a semicolon instead of a comma.z^[{0}] is not a valid test_targets_for_shard argument. No white space is allowed after a comma.)r   rs   #_PACKAGE_OR_CLASS_FOLLOWED_BY_COMMAr   r   r   r   _ANY_SPACE_AFTER_COMMA)r   test_targets     r   ValidateTestTargetsForShardr   +  s    	/	4	4
00k*00==//
",,2F;,?	A A
 ##K00//
",,2F;,?A A 1r   c                     U R                   S:w  d  U R                  (       d  gU R                   Vs/ s H  n[        SU5      PM     snU l        gs  snf )z@Validates list of game-loop scenario numbers, which must be > 0.z	game-loopNr|   )typer|   r<   )r   nums     r   ValidateScenarioNumbersr   =  sL    	YY+T%:%:
&*&;&;=&;s 44FL&;=$ =s   Ac                 r   U R                   (       d  gU R                    H  nUR                  5        H  u  p4UR                  X45      X#'   M     SU;  a  UR                  5       US'   SU;  a  UR	                  5       US'   SU;  a  UR                  5       US'   SU;  d  M  UR                  5       US'   M     g)zFValidates that --device contains a valid set of dimensions and values.Nmodelr   localerH   )ri   r[   r   GetDefaultModelGetDefaultVersionGetDefaultLocaleGetDefaultOrientation)r   r   device_specdimvals        r   ValidateDeviceListr   E  s    	
[[k!'')
$>>sHk * k!(88:k'#*<<>k){")::<k(K'#.#D#D#Fk-  !r   z:^(/private/var/mobile/Media.*|[a-zA-Z0-9.-]+:/Documents.*)c                     [        U S/ 5      (       d  g U R                   HC  n[        R                  U5      (       a  M  [        R
                  " SSR                  U5      5      e   g )Nrk   r   )r   rk   #_IOS_DIRECTORIES_TO_PULL_PATH_REGEXr   r   r   r   )r   r   s     r    ValidateIosDirectoriesToPullListr   ]  s\    	,b	1	1
++i.44Y??//
!5!<!<Y!GI I ,r   )G__doc__
__future__r   r   r   r   r   r   rer   sys$googlecloudsdk.api_lib.firebase.testr   r   r   googlecloudsdk.api_lib.storager   googlecloudsdk.callioper	   googlecloudsdk.core.utilr
   r$   r   
BoundedIntmaxsizer;   r?   Durationr0   r8   rK   rN   r*   r   r.   r5   r9   r<   r@   rC   rI   rE   rO   rS   rV   rX   r^   rc   r   r   r   r   r   r   r   r   compiler   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>r     s    F &  '    	  
 N = 7 / . * 
!7J ",,Q< $//3;;? %%$DI(($D: 7 6? J.JJ
J
JJJJ(@
	
L(22 m 	
 2 0 $ - 9 - ! , % : 2  0!"  #$ )/(!3)0& %%; B-#GL*(Q.3"3,9 **9;L.$< !jj)=> < #%**8#: I( **,- $ M2 A$=G( ')jjA'C #Ir   