
    2                         d Z ddlmZ ddlmZ ddlmZ ddl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 dd	lmZ dd
lmZ ddlZdZdZ G d de      Zd Zd Zy)zACommon test matrix operations used by Firebase Test Lab commands.    )absolute_import)division)unicode_literalsN)
exceptions)util)log)
properties)
console_iog      @z%H:%M:%Sc                   z    e Zd ZdZej                  j
                  dfdZd Zd Zd Z	d Z
d Zd	 Zd
 Zd Zd Zy)MatrixMonitora  A monitor to follow and possibly cancel a single test matrix invocation.

  Attributes:
    matrix_id: {str} the unique ID of the matrix being monitored.
    completed_matrix_states: the set of TestMatrix.State enums representing all
      final matrix states.
  Nc                 F   || _         || _        |d   | _        |d   | _        || _        t        j                         | _        d| _        ||| _	        njt        j                  j                  j                  j                         xs t        | _	        t!        j"                  d      s| xj                  dz  c_	        | j                  j$                  j&                  }|j(                  d|j*                  d	|j,                  d
|j.                  d|j0                  d|j2                  d|j4                  d|j6                  d|j8                  d|j:                  d|j<                  di| _        tA        |j.                  |j0                  |j2                  |j4                  |j6                  |j8                  |j:                  g      | _!        | j                  jD                  j&                  }tA        |j.                  |j0                  |j8                  |j:                  g      | _#        y)aT  Construct a MatrixMonitor to monitor a single test matrix instance.

    Args:
      matrix_id: {str} the unique ID of the matrix being monitored.
      test_type: {str} the type of matrix test being run (e.g. 'robo')
      context: {str:obj} dict containing the gcloud command context, which
        includes the Testing API client & messages libs generated by Apitools.
      clock: injected function which returns a current datetime object when
        called. Used to generate time-stamps on progress messages.
      status_interval_secs: {float} how long to sleep between status checks.
    testing_clienttesting_messagesr   NT)error   
ValidatingPendingRunningFinishedErrorUnsupportedzIncompatible EnvironmentzIncompatible Architecture	CancelledInvalidz*Unspecified*)$	matrix_id
_test_type_client	_messages_clockr   
GetProject_project_max_status_length_status_interval_secsr	   VALUEStestmatrix_status_intervalGetInt_DEFAULT_STATUS_INTERVAL_SECSr
   IsInteractiveTestExecutionStateValueValuesEnum
VALIDATINGPENDINGRUNNINGFINISHEDERRORUNSUPPORTED_ENVIRONMENTINCOMPATIBLE_ENVIRONMENTINCOMPATIBLE_ARCHITECTURE	CANCELLEDINVALIDTEST_STATE_UNSPECIFIED_state_namesset_completed_execution_states
TestMatrixcompleted_matrix_states)selfr   	test_typecontextclockstatus_interval_secsexec_statesmatrix_statess           6lib/googlecloudsdk/api_lib/firebase/test/matrix_ops.py__init__zMatrixMonitor.__init__0   s   " DNDO+,DL/0DNDKOO%DMD'#7d  


 
 
7
7
>
>
@ (
'   %%D1""a'"....CCKYYj7++],,.H--/J{Y**OD (+++,,--, (D$ NN--BBM#&	( $D     c                 $   | j                   j                  j                  }g }t               }|j                  D ]Q  }|j
                  |j                  k(  r%|j                  t        |j                               A|j                  |       S |r>t        j                  j                  dj                  dj                  |                   t        j                  j                  dj                  | j                   t#        |                   |S )zReport unsupported device dimensions and return supported test list.

    Args:
      matrix: a TestMatrix message.

    Returns:
      A list of TestExecution messages which have supported dimensions.
    zDSome device dimensions are not compatible and will be skipped:
  {d}z
  dzFirebase Test Lab will execute your {t} test on {n} device(s). More devices may be added later if flaky test attempts are specified.)tn)r   r)   r*   r7   testExecutionsstater0   add_FormatInvalidDimensionenvironmentappendr   statusPrintformatjoinr   len)r;   matrixstatessupported_testsunsupported_dimensionsr$   s         rB   HandleUnsupportedExecutionsz)MatrixMonitor.HandleUnsupportedExecutionsu   s     ^^))>>FO U%%	v55	5""#:4;K;K#LMt$	 & 	jjFV[[)?@FAC JJ	K	$//S%9	:< rD   c                     | j                         }|j                  D ]  }|j                  |k(  s|c S  t        j                  || j
                        )a  Fetch the TestExecution state of a specific test within a matrix.

    This method is only intended to be used for a TestMatrix with exactly one
    supported TestExecution. It would be inefficient to use it iteratively on
    a larger TestMatrix.

    Args:
      test_id: ID of the TestExecution status to find.

    Returns:
      The TestExecution message matching the unique test_id.
    )GetTestMatrixStatusrJ   idr   TestExecutionNotFoundErrorr   )r;   test_idrU   r$   s       rB   _GetTestExecutionStatusz%MatrixMonitor._GetTestExecutionStatus   sL     %%'F%%	G	 & 
/
/
HHrD   c                    | j                   j                  j                  }d}d}g }d}	 | j                  |      }| j	                         j                  t              }|j                  }	|	r |	j                  xs d}|	j                  xs g }||d D ]?  }
t        j                  j                  dj                  ||
j                                      A t        |      }|j                   |j"                  k(  rt%        j&                  |      |j                   |j(                  k(  r8t%        j*                  dj                  t-        |j.                                    |j                   |k7  rH|j                   }t        j                  j                  dj                  || j0                  |                |j                   | j2                  v rn| j5                          | j7                         }|j                   | j8                  vrYt        j:                  d|j                          | j5                          | j7                         }|j                   | j8                  vrY| j=                  |j                          y)	a  Monitor and report the progress of a single running test.

    This method prints more detailed test progress messages for the case where
    the matrix has exactly one supported test configuration.

    Args:
      test_id: str, the unique id of the single supported test in the matrix.

    Raises:
      TestLabInfrastructureError if the Test service reports a backend error.

     r   Nz{0} {1}zDevice dimensions are not compatible: {d}. Please use "gcloud firebase test android models list" to determine which device dimensions are compatible.rF   z{0} Test is {1}z+Matrix not yet complete, still in state: %s)r   r)   r*   r_   r   strftime_TIMESTAMP_FORMATtestDetailserrorMessageprogressMessagesr   rP   rQ   rR   rstriprT   rK   r/   r   TestLabInfrastructureErrorr0   AllDimensionsIncompatibleErrorrM   rN   r6   r8   _SleepForStatusIntervalr[   r:   debug_LogTestComplete)r;   r^   rV   
last_stater   progresslast_progress_lenrP   	timestampdetailsmsgrU   s               rB   MonitorTestExecutionProgressz*MatrixMonitor.MonitorTestExecutionProgress   s#    ^^))>>FJEH
++G4f++-(():;i""g	$$*++1r +,-#

)))SZZ\BC .h-		%33E::	77	777@@F)&*<*<= AG A?@ 	@ 
	#\\


*11t((46 	7 
99	9
""$C J %%'F
,,d::
:	ii=v||L
""$'')f ,,d::
: 	&,,'
rD   c                 "   | j                   j                  | j                  | j                        }	 | j                  j
                  j                  |      S # t        j                  $ r#}t        j                  |      }d|_        |d}~ww xY w)zFetch the response from the GetTestMatrix rpc.

    Returns:
      A TestMatrix message holding the current state of the created tests.

    Raises:
      HttpException if the Test service reports a backend error.
    	projectIdtestMatrixIdz=Http error {status_code} while monitoring test run: {message}N)r   %TestingProjectsTestMatricesGetRequestr    r   r   projects_testMatricesGetapitools_exceptions	HttpErrorcalliope_exceptionsHttpExceptionerror_formatr;   requesteexcs       rB   r[   z!MatrixMonitor.GetTestMatrixStatus   s     nnBB--dnn C >G\\//33G<<(( --a0c
I 
i	s   $A B+B		Bc                 R   	 | j                         }t        j                  t              }|j                  D ]  }||j
                  xx   dz  cc<    | j                  |       |j
                  | j                  v r| j                  |j
                         y| j                          )zFMonitor and report the progress of multiple running tests in a matrix.   N)
r[   collectionsdefaultdictintrJ   rK   _UpdateMatrixStatusr:   rl   rj   )r;   rU   state_countsr$   s       rB   MonitorTestMatrixProgressz'MatrixMonitor.MonitorTestMatrixProgress   s    
'')f ,,S1l''$TZZ A%  ( |,	55	5fll+
""$ rD   c                    g }| j                         j                  t              }t        j                  |      D ]:  \  }}|dkD  s|j                  dj                  | j                  |   |             < |j                          dj                  |dj                  |            }t        t        |      | j                        | _        t        j                  j                  |j!                  | j                               y)zUpdate the matrix status line with the current test state counts.

    Example: 'Test matrix status: Finished:5 Running:3 Unsupported:2'

    Args:
      state_counts: {state:count} a dict mapping a test state to its frequency.
    r   z{s}:{c})scz{0} Test matrix status: {1}  N)r   rb   rc   six	iteritemsrO   rR   r6   sortrS   maxrT   r!   r   rP   writeljust)r;   r   rP   rp   rK   countouts          rB   r   z!MatrixMonitor._UpdateMatrixStatus	  s     F&&'89Il3u	i&&):):5)AU&KL 4 KKM
*
1
1)SXXf=M
NC "#c(D,C,CDDJJSYYt6678rD   c                     t        j                  dj                  |             t         j                  j	                  dj                  | j
                  j                                      y)z?Let the user know that their test matrix has completed running.z#Test matrix completed in state: {0}z
{0} testing complete.N)r   inforR   rP   rQ   r   
capitalize)r;   matrix_states     rB   rl   zMatrixMonitor._LogTestComplete  sJ    HH299,GHJJ.55""$& 'rD   c                 B    t        j                  | j                         y )N)timesleepr"   )r;   s    rB   rj   z%MatrixMonitor._SleepForStatusInterval$  s    JJt))*rD   c                 $   | j                   j                  | j                  | j                        }	 | j                  j
                  j                  |       y# t        j                  $ r#}t        j                  |      }d|_        |d}~ww xY w)zvCancels an in-progress TestMatrix.

    Raises:
      HttpException if the Test service reports a back-end error.
    ru   zCancelTestMatrix: {message}N)r   (TestingProjectsTestMatricesCancelRequestr    r   r   ry   Cancelr{   r|   r}   r~   r   r   s       rB   CancelTestMatrixzMatrixMonitor.CancelTestMatrix'  s{     nnEE--dnn F >G
ll((//8(( --a0c6cis   %A B,B

B)__name__
__module____qualname____doc__datetimenowrC   rY   r_   rs   r[   r   r   rl   rj   r    rD   rB   r   r   '   sQ     &&**$(CJ:I(>@&% 9*'+rD   r   c                    t        | dd      3| j                  }dj                  |j                  |j                        S t        | dd      3| j
                  }dj                  |j                  |j                        S y)zHReturn a human-readable string representing an invalid matrix dimension.androidDeviceNz[OS-version {vers} on {model}])modelvers	iosDevicez[unknown-environment])getattrr   rR   androidModelIdandroidVersionIdr   
iosModelIdiosVersionId)rN   devices     rB   rM   rM   7  s    [/40<&&F,33##&*A*A 4 C D[+t,8""F,33f&9&9 4 ; < 
!rD   c                 &    dj                  |       S )a9  Reformat a Duration arg to work around ApiTools non-support of that type.

  Duration args are normally converted to an int in seconds (e.g. --timeout 5m
  becomes args.timeout with int value 300). Duration proto fields are converted
  to type string during discovery doc creation, so we have to convert the int
  back into a string-formatted Duration (i.e. append an 's') before
  passing it to the Testing Service.

  Args:
    duration: {int} the number of seconds in the time duration.

  Returns:
    String representation of the Duration with units of seconds.
  z{secs}s)secs)rR   )durations    rB   ReformatDurationr   E  s     
		x		((rD   )r   
__future__r   r   r   r   r   r   apitools.base.pyr   r{   $googlecloudsdk.api_lib.firebase.testr   googlecloudsdk.callioper}   googlecloudsdk.corer   r	   googlecloudsdk.core.consoler
   r   r'   rc   objectr   rM   r   r   rD   rB   <module>r      sZ    H &  '    > ; 5 E # * 2 
 #  MF M`!)rD   