@ -6,11 +6,12 @@ import shutil 
			
		
	
		
		
			
				
					
					import  subprocess import  subprocess  
			
		
	
		
		
			
				
					
					import  time import  time  
			
		
	
		
		
			
				
					
					import  unittest import  unittest  
			
		
	
		
		
			
				
					
					from  parameterized  import  parameterized  
			
		
	
		
		
			
				
					
					from  pathlib  import  Path from  pathlib  import  Path  
			
		
	
		
		
			
				
					
					from  tqdm  import  trange  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					from  common . params  import  Params from  common . params  import  Params  
			
		
	
		
		
			
				
					
					from  common . hardware  import  EON ,  TICI from  common . hardware  import  EON ,  TICI  
			
		
	
		
		
			
				
					
					from  common . timeout  import  Timeout  
			
		
	
		
		
			
				
					
					from  selfdrive . test . helpers  import  with_processes from  selfdrive . test . helpers  import  with_processes  
			
		
	
		
		
			
				
					
					from  selfdrive . loggerd . config  import  ROOT ,  CAMERA_FPS from  selfdrive . loggerd . config  import  ROOT ,  CAMERA_FPS  
			
		
	
		
		
			
				
					
					
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -21,9 +22,14 @@ if EON: 
			
		
	
		
		
			
				
					
					  CAMERAS  =  {    CAMERAS  =  {   
			
		
	
		
		
			
				
					
					    " fcamera " :  FULL_SIZE ,      " fcamera " :  FULL_SIZE ,   
			
		
	
		
		
			
				
					
					    " dcamera " :  770920 ,      " dcamera " :  770920 ,   
			
		
	
		
		
			
				
					
					    " qcamera " :  38533 ,   
			
		
	
		
		
			
				
					
					  }    }   
			
		
	
		
		
			
				
					
					elif  TICI : elif  TICI :  
			
		
	
		
		
			
				
					
					  CAMERAS  =  { f " { c } camera " :  FULL_SIZE  for  c  in  [ " f " ,  " e " ,  " d " ] }    CAMERAS  =  { f " { c } camera " :  FULL_SIZE  for  c  in  [ " f " ,  " e " ,  " d " ] }   
			
		
	
		
		
			
				
					
					else :  
			
		
	
		
		
			
				
					
					  CAMERAS  =  { }   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					ALL_CAMERA_COMBINATIONS  =  [ ( cameras , )  for  cameras  in  [ CAMERAS ,  { k : CAMERAS [ k ]  for  k  in  CAMERAS  if  k != ' dcamera ' } ] ]  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					FRAME_TOLERANCE  =  2 FRAME_TOLERANCE  =  2  
			
		
	
		
		
			
				
					
					FILE_SIZE_TOLERANCE  =  0.25 FILE_SIZE_TOLERANCE  =  0.25  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -37,7 +43,6 @@ class TestLoggerd(unittest.TestCase): 
			
		
	
		
		
			
				
					
					      raise  unittest . SkipTest        raise  unittest . SkipTest   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  def  setUp ( self ) :    def  setUp ( self ) :   
			
		
	
		
		
			
				
					
					    Params ( ) . put ( " RecordFront " ,  " 1 " )   
			
		
	
		
		
			
				
					
					    self . _clear_logs ( )      self . _clear_logs ( )   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    self . segment_length  =  2      self . segment_length  =  2   
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -55,28 +60,27 @@ class TestLoggerd(unittest.TestCase): 
			
		
	
		
		
			
				
					
					    last_route  =  sorted ( Path ( ROOT ) . iterdir ( ) ,  key = os . path . getmtime ) [ - 1 ]      last_route  =  sorted ( Path ( ROOT ) . iterdir ( ) ,  key = os . path . getmtime ) [ - 1 ]   
			
		
	
		
		
			
				
					
					    return  os . path . join ( ROOT ,  last_route )      return  os . path . join ( ROOT ,  last_route )   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  # TODO: this should run faster than real time   
			
		
	
		
		
			
				
					
					  @with_processes ( [ ' camerad ' ,  ' loggerd ' ] ,  init_time = 5 )    @with_processes ( [ ' camerad ' ,  ' loggerd ' ] ,  init_time = 5 )   
			
		
	
		
		
			
				
					
					  def  test_log_rotation ( self ) :    def  _log_data ( self ,  t ) :   
			
				
				
			
		
	
		
		
			
				
					
					    # wait for first seg to start being written      time . sleep ( t )   
			
				
				
			
		
	
		
		
			
				
					
					    time . sleep ( 5 )  
 
			
				
				
			
		
	
		
		
			
				
					
					    route_prefix_path  =  self . _get_latest_segment_path ( ) . rsplit ( " -- " ,  1 ) [ 0 ]    # TODO: this should run faster than real time   
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					  @parameterized . expand ( ALL_CAMERA_COMBINATIONS )   
			
		
	
		
		
			
				
					
					  def  test_log_rotation ( self ,  cameras ) :   
			
		
	
		
		
			
				
					
					    print ( " checking targets: " ,  cameras )   
			
		
	
		
		
			
				
					
					    Params ( ) . put ( " RecordFront " ,  " 1 "  if  ' dcamera '  in  cameras  else  " 0 " )   
			
		
	
		
		
			
				
					
					    time . sleep ( 1 )   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    num_segments  =  random . randint ( 80 ,  150 )      num_segments  =  random . randint ( 80 ,  150 )   
			
		
	
		
		
			
				
					
					    for  i  in  range ( num_segments ) :      self . _log_data ( self . segment_length  *  num_segments  +  5 )   
			
				
				
			
		
	
		
		
			
				
					
					      if  i  <  num_segments  -  1 :      time . sleep ( 5 )   
			
				
				
			
		
	
		
		
			
				
					
					        with  Timeout ( self . segment_length * 3 ,  error_msg = f " timed out waiting for segment  { i } " ) :   
			
		
	
		
		
			
				
					
					          while  True :   
			
		
	
		
		
			
				
					
					            seg_num  =  int ( self . _get_latest_segment_path ( ) . rsplit ( " -- " ,  1 ) [ 1 ] )   
			
		
	
		
		
			
				
					
					            if  seg_num  >  i :   
			
		
	
		
		
			
				
					
					              break   
			
		
	
		
		
			
				
					
					            time . sleep ( 0.1 )   
			
		
	
		
		
			
				
					
					      else :   
			
		
	
		
		
			
				
					
					        time . sleep ( self . segment_length  +  2 )   
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    route_prefix_path  =  self . _get_latest_segment_path ( ) . rsplit ( " -- " ,  1 ) [ 0 ]   
			
		
	
		
		
			
				
					
					    for  i  in  trange ( num_segments ) :   
			
		
	
		
		
			
				
					
					      # check each camera file size        # check each camera file size   
			
		
	
		
		
			
				
					
					      for  camera ,  size  in  CAMERAS . items ( ) :        for  camera ,  size  in  cameras . items ( ) :   
			
				
				
			
		
	
		
		
			
				
					
					        file_path  =  f " { route_prefix_path } -- { i } / { camera } .hevc "          ext  =  " ts "  if  camera == ' qcamera '  else  " hevc "   
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					        file_path  =  f " { route_prefix_path } -- { i } / { camera } . { ext } "   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					        # check file size          # check file size   
			
		
	
		
		
			
				
					
					        self . assertTrue ( os . path . exists ( file_path ) ,  f " couldn ' t find  { file_path } " )          self . assertTrue ( os . path . exists ( file_path ) ,  f " couldn ' t find  { file_path } " )   
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -84,10 +88,13 @@ class TestLoggerd(unittest.TestCase): 
			
		
	
		
		
			
				
					
					        self . assertTrue ( math . isclose ( file_size ,  size ,  rel_tol = FILE_SIZE_TOLERANCE ) ,          self . assertTrue ( math . isclose ( file_size ,  size ,  rel_tol = FILE_SIZE_TOLERANCE ) ,   
			
		
	
		
		
			
				
					
					                        f " { camera }  failed size check: expected  { size } , got  { file_size } " )                          f " { camera }  failed size check: expected  { size } , got  { file_size } " )   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					        if  camera  ==  ' qcamera ' :   
			
		
	
		
		
			
				
					
					          continue   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					        # check frame count          # check frame count   
			
		
	
		
		
			
				
					
					        cmd  =  f " ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames  \          cmd  =  f " ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames  \   
			
		
	
		
		
			
				
					
					               - of  default = nokey = 1 : noprint_wrappers = 1  { file_path } "                 - of  default = nokey = 1 : noprint_wrappers = 1  { file_path } "   
			
		
	
		
		
			
				
					
					        expected_frames  =  self . segment_length  *  CAMERA_FPS          expected_frames  =  self . segment_length  *  CAMERA_FPS  / /  2  if  ( EON  and  camera == ' dcamera ' )  else  self . segment_length  *  CAMERA_FPS    
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					        frame_count  =  int ( subprocess . check_output ( cmd ,  shell = True ,  encoding = ' utf8 ' ) . strip ( ) )          frame_count  =  int ( subprocess . check_output ( cmd ,  shell = True ,  encoding = ' utf8 ' ) . strip ( ) )   
			
		
	
		
		
			
				
					
					        self . assertTrue ( abs ( expected_frames  -  frame_count )  < =  FRAME_TOLERANCE ,          self . assertTrue ( abs ( expected_frames  -  frame_count )  < =  FRAME_TOLERANCE ,   
			
		
	
		
		
			
				
					
					                        f " { camera }  failed frame count check: expected  { expected_frames } , got  { frame_count } " )                          f " { camera }  failed frame count check: expected  { expected_frames } , got  { frame_count } " )