# include  <dirent.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <sys/stat.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <sys/types.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <algorithm> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <climits> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <random> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <string> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define CATCH_CONFIG_MAIN 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "catch2/catch.hpp" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "common/util.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								std : : string  random_bytes ( int  size )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : random_device  rd ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : independent_bits_engine < std : : default_random_engine ,  CHAR_BIT ,  unsigned  char >  rbe ( rd ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : string  bytes ( size  +  1 ,  ' \0 ' ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : generate ( bytes . begin ( ) ,  bytes . end ( ) ,  std : : ref ( rbe ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  bytes ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								TEST_CASE ( " util::read_file " )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SECTION ( " read /proc/version " )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  ret  =  util : : read_file ( " /proc/version " ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( ret . find ( " Linux version " )  ! =  std : : string : : npos ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SECTION ( " read from sysfs " )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  ret  =  util : : read_file ( " /sys/power/wakeup_count " ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( ! ret . empty ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SECTION ( " read file " )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    char  filename [ ]  =  " /tmp/test_read_XXXXXX " ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    int  fd  =  mkstemp ( filename ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( util : : read_file ( filename ) . empty ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  content  =  random_bytes ( 64  *  1024 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    write ( fd ,  content . c_str ( ) ,  content . size ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  ret  =  util : : read_file ( filename ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( ret  = =  content ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    close ( fd ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SECTION ( " read directory " )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( util : : read_file ( " . " ) . empty ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SECTION ( " read non-existent file " )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  ret  =  util : : read_file ( " does_not_exist " ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( ret . empty ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SECTION ( " read non-permission " )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( util : : read_file ( " /proc/kmsg " ) . empty ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								TEST_CASE ( " util::file_exists " )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  char  filename [ ]  =  " /tmp/test_file_exists_XXXXXX " ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  fd  =  mkstemp ( filename ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  REQUIRE ( fd  ! =  - 1 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  close ( fd ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SECTION ( " existent file " )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( util : : file_exists ( filename ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( util : : file_exists ( " /tmp " ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SECTION ( " nonexistent file " )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  fn  =  filename ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( ! util : : file_exists ( fn  +  " /nonexistent " ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SECTION ( " file has no access permissions " )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  fn  =  " /proc/kmsg " ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : ifstream  f ( fn ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( f . good ( )  = =  false ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( util : : file_exists ( fn ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  : : remove ( filename ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								TEST_CASE ( " util::read_files_in_dir " )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  char  tmp_path [ ]  =  " /tmp/test_XXXXXX " ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  const  std : : string  test_path  =  mkdtemp ( tmp_path ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  const  std : : string  files [ ]  =  { " .test1 " ,  " 'test2' " ,  " test3 " } ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for  ( auto  fn  :  files )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : ofstream { test_path  +  " / "  +  fn }  < <  fn ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mkdir ( ( test_path  +  " /dir " ) . c_str ( ) ,  0777 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : map < std : : string ,  std : : string >  result  =  util : : read_files_in_dir ( test_path ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  REQUIRE ( result . find ( " dir " )  = =  result . end ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  REQUIRE ( result . size ( )  = =  std : : size ( files ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for  ( auto &  [ k ,  v ]  :  result )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( k  = =  v ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								TEST_CASE ( " util::safe_fwrite " )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  char  filename [ ]  =  " /tmp/XXXXXX " ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  fd  =  mkstemp ( filename ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  close ( fd ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : string  dat  =  random_bytes ( 1024  *  1024 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  FILE  * f  =  util : : safe_fopen ( filename ,  " wb " ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  REQUIRE ( f  ! =  nullptr ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  size  =  util : : safe_fwrite ( dat . data ( ) ,  1 ,  dat . size ( ) ,  f ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  REQUIRE ( size  = =  dat . size ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  ret  =  util : : safe_fflush ( f ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  REQUIRE ( ret  = =  0 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ret  =  fclose ( f ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  REQUIRE ( ret  = =  0 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  REQUIRE ( dat  = =  util : : read_file ( filename ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								TEST_CASE ( " util::create_directories " )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  system ( " rm /tmp/test_create_directories -rf " ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : string  dir  =  " /tmp/test_create_directories/a/b/c/d/e/f " ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  auto  check_dir_permissions  =  [ ] ( const  std : : string  & dir ,  mode_t  mode )  - >  bool  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    struct  stat  st  =  { } ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  stat ( dir . c_str ( ) ,  & st )  = =  0  & &  ( st . st_mode  &  S_IFMT )  = =  S_IFDIR  & &  ( st . st_mode  &  ( S_IRWXU  |  S_IRWXG  |  S_IRWXO ) )  = =  mode ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SECTION ( " create_directories " )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( util : : create_directories ( dir ,  0755 ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( check_dir_permissions ( dir ,  0755 ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SECTION ( " dir already exists " )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( util : : create_directories ( dir ,  0755 ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( util : : create_directories ( dir ,  0755 ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SECTION ( " a file exists with the same name " )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( util : : create_directories ( dir ,  0755 ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    int  f  =  open ( ( dir  +  " /file " ) . c_str ( ) ,  O_RDWR  |  O_CREAT ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( f  ! =  - 1 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    close ( f ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( util : : create_directories ( dir  +  " /file " ,  0755 )  = =  false ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( util : : create_directories ( dir  +  " /file/1/2/3 " ,  0755 )  = =  false ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  SECTION ( " end with slashes " )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( util : : create_directories ( dir  +  " / " ,  0755 ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SECTION ( " empty " )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( util : : create_directories ( " " ,  0755 )  = =  false ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								TEST_CASE ( " util::remove_files_in_dir " )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : string  tmp_dir  =  " /tmp/test_remove_all_in_dir " ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  system ( " rm /tmp/test_remove_all_in_dir -rf " ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  REQUIRE ( util : : create_directories ( tmp_dir ,  0755 ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  const  int  tmp_file_cnt  =  10 ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for  ( int  i  =  0 ;  i  <  tmp_file_cnt ;  + + i )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  tmp_file  =  tmp_dir  +  " /test_XXXXXX " ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    int  fd  =  mkstemp ( ( char * ) tmp_file . c_str ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    close ( fd ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    REQUIRE ( util : : file_exists ( tmp_file . c_str ( ) ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  REQUIRE ( util : : read_files_in_dir ( tmp_dir ) . size ( )  = =  tmp_file_cnt ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  util : : remove_files_in_dir ( tmp_dir ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  REQUIRE ( util : : read_files_in_dir ( tmp_dir ) . empty ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}