DECLARE_TEST( fs, directory ) { char* longpath; char* testpath = path_merge( environment_temporary_directory(), string_from_int_static( random64(), 0, 0 ) ); if( !fs_is_file( testpath ) ) fs_remove_file( testpath ); if( !fs_is_directory( testpath ) ) fs_make_directory( testpath ); EXPECT_TRUE( fs_is_directory( testpath ) ); fs_remove_directory( testpath ); EXPECT_FALSE( fs_is_directory( testpath ) ); longpath = path_merge( testpath, string_from_int_static( random64(), 0, 0 ) ); EXPECT_FALSE( fs_is_directory( longpath ) ); fs_make_directory( longpath ); EXPECT_TRUE( fs_is_directory( longpath ) ); fs_remove_directory( testpath ); EXPECT_FALSE( fs_is_directory( testpath ) ); EXPECT_FALSE( fs_is_directory( longpath ) ); string_deallocate( longpath ); string_deallocate( testpath ); return 0; }
DECLARE_TEST( fs, util ) { tick_t systime = time_system(); tick_t lastmod = 0; char* testpath = path_merge( environment_temporary_directory(), string_from_int_static( random64(), 0, 0 ) ); if( !fs_is_directory( environment_temporary_directory() ) ) fs_make_directory( environment_temporary_directory() ); if( fs_is_directory( testpath ) ) fs_remove_directory( testpath ); fs_remove_file( testpath ); EXPECT_EQ( fs_last_modified( testpath ), 0 ); thread_sleep( 1000 ); //For fs time granularity, make sure at least one second passed since systime stream_deallocate( fs_open_file( testpath, STREAM_OUT ) ); EXPECT_TRUE( fs_is_file( testpath ) ); EXPECT_GE( fs_last_modified( testpath ), systime ); fs_remove_file( testpath ); EXPECT_FALSE( fs_is_file( testpath ) ); EXPECT_EQ( fs_last_modified( testpath ), 0 ); stream_deallocate( fs_open_file( testpath, STREAM_OUT ) ); EXPECT_TRUE( fs_is_file( testpath ) ); EXPECT_GE( fs_last_modified( testpath ), systime ); lastmod = fs_last_modified( testpath ); thread_sleep( 5000 ); EXPECT_EQ( fs_last_modified( testpath ), lastmod ); fs_touch( testpath ); EXPECT_GT( fs_last_modified( testpath ), lastmod ); fs_remove_file( testpath ); string_deallocate( testpath ); return 0; }
const char* environment_home_directory( void ) { if( _environment_home_dir[0] ) return _environment_home_dir; #if FOUNDATION_PLATFORM_WINDOWS { char* path; wchar_t* wpath = memory_allocate_zero( sizeof( wchar_t ) * FOUNDATION_MAX_PATHLEN, 0, MEMORY_TEMPORARY ); SHGetFolderPathW( 0, CSIDL_LOCAL_APPDATA, 0, 0, wpath ); path = path_clean( string_allocate_from_wstring( wpath, 0 ), true ); string_copy( _environment_home_dir, path, FOUNDATION_MAX_PATHLEN ); string_deallocate( path ); memory_deallocate( wpath ); } #elif FOUNDATION_PLATFORM_LINUX string_copy( _environment_home_dir, environment_variable( "HOME" ), FOUNDATION_MAX_PATHLEN ); #elif FOUNDATION_PLATFORM_APPLE if( environment_application()->flags & APPLICATION_UTILITY ) { CFStringRef home = NSHomeDirectory(); CFStringGetCString( home, _environment_home_dir, FOUNDATION_MAX_PATHLEN, kCFStringEncodingUTF8 ); } else { char bundle_identifier[FOUNDATION_MAX_PATHLEN+1]; environment_bundle_identifier( bundle_identifier ); char* path = path_append( path_merge( _environment_home_dir, "/Library/Application Support" ), bundle_identifier ); string_copy( _environment_home_dir, path, FOUNDATION_MAX_PATHLEN ); string_deallocate( path ); } #elif FOUNDATION_PLATFORM_ANDROID string_copy( _environment_home_dir, android_app()->activity->internalDataPath, FOUNDATION_MAX_PATHLEN ); #else # error Not implemented #endif return _environment_home_dir; }
int main_run( void* main_arg ) { #if !BUILD_MONOLITHIC const char* pattern = 0; char** exe_paths = 0; unsigned int iexe, exesize; process_t* process = 0; char* process_path = 0; unsigned int* exe_flags = 0; #endif #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID || FOUNDATION_PLATFORM_PNACL int remain_counter = 0; #endif #if BUILD_DEBUG const char* build_name = "debug"; #elif BUILD_RELEASE const char* build_name = "release"; #elif BUILD_PROFILE const char* build_name = "profile"; #elif BUILD_DEPLOY const char* build_name = "deploy"; #endif int process_result = 0; object_t thread = 0; FOUNDATION_UNUSED( main_arg ); FOUNDATION_UNUSED( build_name ); log_set_suppress( HASH_TEST, ERRORLEVEL_DEBUG ); log_infof( HASH_TEST, "Foundation library v%s built for %s using %s (%s)", string_from_version_static( foundation_version() ), FOUNDATION_PLATFORM_DESCRIPTION, FOUNDATION_COMPILER_DESCRIPTION, build_name ); thread = thread_create( event_thread, "event_thread", THREAD_PRIORITY_NORMAL, 0 ); thread_start( thread, 0 ); while( !thread_is_running( thread ) ) thread_sleep( 10 ); #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID while( !_test_should_start ) { #if FOUNDATION_PLATFORM_ANDROID system_process_events(); #endif thread_sleep( 100 ); } #endif fs_remove_directory( environment_temporary_directory() ); #if BUILD_MONOLITHIC test_run_fn tests[] = { test_app_run, test_array_run, test_atomic_run, test_base64_run, test_bitbuffer_run, test_blowfish_run, test_bufferstream_run, test_config_run, test_crash_run, test_environment_run, test_error_run, test_event_run, test_fs_run, test_hash_run, test_hashmap_run, test_hashtable_run, test_library_run, test_math_run, test_md5_run, test_mutex_run, test_objectmap_run, test_path_run, test_pipe_run, test_process_run, test_profile_run, test_radixsort_run, test_random_run, test_regex_run, test_ringbuffer_run, test_semaphore_run, test_stacktrace_run, test_stream_run, //stream test closes stdin test_string_run, test_system_run, test_time_run, test_uuid_run, 0 }; #if FOUNDATION_PLATFORM_ANDROID object_t test_thread = thread_create( test_runner, "test_runner", THREAD_PRIORITY_NORMAL, 0 ); thread_start( test_thread, tests ); log_debug( HASH_TEST, "Starting test runner thread" ); while( !thread_is_running( test_thread ) ) { system_process_events(); thread_sleep( 10 ); } while( thread_is_running( test_thread ) ) { system_process_events(); thread_sleep( 10 ); } process_result = (int)(intptr_t)thread_result( test_thread ); thread_destroy( test_thread ); while( thread_is_thread( test_thread ) ) { system_process_events(); thread_sleep( 10 ); } #else process_result = (int)(intptr_t)test_runner( 0, tests ); #endif if( process_result != 0 ) log_warnf( HASH_TEST, WARNING_SUSPICIOUS, "Tests failed with exit code %d", process_result ); #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID || FOUNDATION_PLATFORM_PNACL while( !_test_should_terminate && _test_have_focus && ( remain_counter < 50 ) ) { system_process_events(); thread_sleep( 100 ); ++remain_counter; } #endif log_debug( HASH_TEST, "Exiting main loop" ); #else // !BUILD_MONOLITHIC //Find all test executables in the current executable directory #if FOUNDATION_PLATFORM_WINDOWS pattern = "^test-.*\\.exe$"; #elif FOUNDATION_PLATFORM_MACOSX pattern = "^test-.*$"; #elif FOUNDATION_PLATFORM_POSIX pattern = "^test-.*$"; #else # error Not implemented #endif exe_paths = fs_matching_files( environment_executable_directory(), pattern, false ); array_resize( exe_flags, array_size( exe_paths ) ); memset( exe_flags, 0, sizeof( unsigned int ) * array_size( exe_flags ) ); #if FOUNDATION_PLATFORM_MACOSX //Also search for test applications const char* app_pattern = "^test-.*\\.app$"; regex_t* app_regex = regex_compile( app_pattern ); char** subdirs = fs_subdirs( environment_executable_directory() ); for( int idir = 0, dirsize = array_size( subdirs ); idir < dirsize; ++idir ) { if( regex_match( app_regex, subdirs[idir], string_length( subdirs[idir] ), 0, 0 ) ) { array_push( exe_paths, string_substr( subdirs[idir], 0, string_length( subdirs[idir] ) - 4 ) ); array_push( exe_flags, PROCESS_MACOSX_USE_OPENAPPLICATION ); } } string_array_deallocate( subdirs ); regex_deallocate( app_regex ); #endif for( iexe = 0, exesize = array_size( exe_paths ); iexe < exesize; ++iexe ) { bool is_self = false; char* exe_file_name = path_base_file_name( exe_paths[iexe] ); if( string_equal( exe_file_name, environment_executable_name() ) ) is_self = true; string_deallocate( exe_file_name ); if( is_self ) continue; //Don't run self process_path = path_merge( environment_executable_directory(), exe_paths[iexe] ); process = process_allocate(); process_set_executable_path( process, process_path ); process_set_working_directory( process, environment_executable_directory() ); process_set_flags( process, PROCESS_ATTACHED | exe_flags[iexe] ); log_infof( HASH_TEST, "Running test executable: %s", exe_paths[iexe] ); process_result = process_spawn( process ); while( process_result == PROCESS_WAIT_INTERRUPTED ) { thread_sleep( 10 ); process_result = process_wait( process ); } process_deallocate( process ); string_deallocate( process_path ); if( process_result != 0 ) { if( process_result >= PROCESS_INVALID_ARGS ) log_warnf( HASH_TEST, WARNING_SUSPICIOUS, "Tests failed, process terminated with error %x", process_result ); else log_warnf( HASH_TEST, WARNING_SUSPICIOUS, "Tests failed with exit code %d", process_result ); process_set_exit_code( -1 ); goto exit; } log_infof( HASH_TEST, "All tests from %s passed (%d)", exe_paths[iexe], process_result ); } log_info( HASH_TEST, "All tests passed" ); exit: if( exe_paths ) string_array_deallocate( exe_paths ); array_deallocate( exe_flags ); #endif thread_terminate( thread ); thread_destroy( thread ); while( thread_is_running( thread ) ) thread_sleep( 10 ); while( thread_is_thread( thread ) ) thread_sleep( 10 ); log_infof( HASH_TEST, "Tests exiting: %d", process_result ); return process_result; }
DECLARE_TEST( profile, stream ) { object_t thread[32]; int ith; int frame; char* filename; error(); filename = path_merge( environment_temporary_directory(), "test.profile" ); log_infof( HASH_TEST, "Output to profile file: %s", filename ); fs_make_directory( environment_temporary_directory() ); _profile_stream = fs_open_file( filename, STREAM_OUT | STREAM_BINARY ); string_deallocate( filename ); profile_initialize( "test_profile", _test_profile_buffer, _test_profile_buffer_size ); profile_set_output( _profile_file_writer ); profile_set_output_wait( 10 ); profile_enable( true ); for( ith = 0; ith < 32; ++ith ) { thread[ith] = thread_create( _profile_stream_thread, "profile_thread", THREAD_PRIORITY_NORMAL, 0 ); thread_start( thread[ith], 0 ); } test_wait_for_threads_startup( thread, 32 ); for( frame = 0; frame < 1000; ++frame ) { thread_sleep( 16 ); profile_log( "This is a really long profile log line that should break into multiple profile blocks automatically without causing any issues whatsoever if everything works as expected which it should or the code needs to be fixed" ); profile_end_frame( frame++ ); if( ( frame % 30 ) == 0 ) { profile_enable( false ); thread_sleep( 10 ); profile_enable( true ); } } for( ith = 0; ith < 32; ++ith ) { thread_terminate( thread[ith] ); thread_destroy( thread[ith] ); thread_yield(); } test_wait_for_threads_exit( thread, 32 ); profile_end_frame( frame++ ); profile_set_output_wait( 100 ); thread_sleep( 1000 ); profile_enable( false ); profile_shutdown(); error(); stream_deallocate( _profile_stream ); //TODO: Validate that output is sane log_debugf( HASH_TEST, "Generated %lld blocks", atomic_load64( &_profile_generated_blocks ) ); return 0; }
DECLARE_TEST( fs, file ) { char* testpath = path_merge( environment_temporary_directory(), string_from_int_static( random64(), 0, 0 ) ); char* copypath = path_merge( environment_temporary_directory(), string_from_int_static( random64(), 0, 0 ) ); stream_t* teststream = 0; if( !fs_is_directory( environment_temporary_directory() ) ) fs_make_directory( environment_temporary_directory() ); if( fs_is_directory( testpath ) ) fs_remove_directory( testpath ); fs_remove_file( testpath ); if( fs_is_directory( copypath ) ) fs_remove_directory( copypath ); fs_remove_file( copypath ); teststream = fs_open_file( testpath, STREAM_IN ); EXPECT_EQ( teststream, 0 ); EXPECT_FALSE( fs_is_file( testpath ) ); teststream = fs_open_file( testpath, STREAM_IN | STREAM_OUT ); EXPECT_NE( teststream, 0 ); EXPECT_TRUE( fs_is_file( testpath ) ); stream_deallocate( teststream ); fs_remove_file( testpath ); teststream = fs_open_file( testpath, STREAM_IN ); EXPECT_EQ( teststream, 0 ); EXPECT_FALSE( fs_is_file( testpath ) ); teststream = fs_open_file( testpath, STREAM_OUT ); EXPECT_NE( teststream, 0 ); EXPECT_TRUE( fs_is_file( testpath ) ); stream_deallocate( teststream ); teststream = 0; fs_copy_file( testpath, copypath ); EXPECT_TRUE( fs_is_file( copypath ) ); fs_remove_file( copypath ); EXPECT_FALSE( fs_is_file( copypath ) ); teststream = fs_open_file( testpath, STREAM_OUT ); EXPECT_NE( teststream, 0 ); EXPECT_TRUE( fs_is_file( testpath ) ); stream_write_string( teststream, "testing testing" ); stream_deallocate( teststream ); teststream = 0; fs_copy_file( testpath, copypath ); EXPECT_TRUE( fs_is_file( copypath ) ); fs_remove_file( copypath ); EXPECT_FALSE( fs_is_file( copypath ) ); stream_deallocate( teststream ); string_deallocate( testpath ); string_deallocate( copypath ); return 0; }
DECLARE_TEST( fs, monitor ) { char* testpath = path_merge( environment_temporary_directory(), string_from_int_static( random64(), 0, 0 ) ); char* filetestpath = path_merge( testpath, string_from_int_static( random64(), 0, 0 ) ); stream_t* test_stream; event_stream_t* stream; event_block_t* block; event_t* event; stream = fs_event_stream(); if( fs_is_file( testpath ) ) fs_remove_file( testpath ); if( !fs_is_directory( testpath ) ) fs_make_directory( testpath ); if( fs_is_file( filetestpath ) ) fs_remove_file( filetestpath ); stream_deallocate( fs_open_file( filetestpath, STREAM_OUT ) ); fs_remove_file( filetestpath ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_EQ( event, 0 ); fs_monitor( testpath ); thread_sleep( 1000 ); stream_deallocate( fs_open_file( filetestpath, STREAM_OUT ) ); thread_sleep( 100 ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_NE( event, 0 ); EXPECT_EQ( event->system, SYSTEM_FOUNDATION ); EXPECT_EQ( event->id, FOUNDATIONEVENT_FILE_CREATED ); EXPECT_STREQ( event->payload, filetestpath ); event = event_next( block, event ); EXPECT_EQ( event, 0 ); test_stream = fs_open_file( filetestpath, STREAM_IN | STREAM_OUT ); stream_write_string( test_stream, filetestpath ); stream_deallocate( test_stream ); thread_sleep( 100 ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_NE( event, 0 ); EXPECT_EQ( event->system, SYSTEM_FOUNDATION ); EXPECT_EQ( event->id, FOUNDATIONEVENT_FILE_MODIFIED ); EXPECT_STREQ( event->payload, filetestpath ); event = event_next( block, event ); EXPECT_EQ( event, 0 ); fs_remove_file( filetestpath ); thread_sleep( 100 ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_NE( event, 0 ); EXPECT_EQ( event->system, SYSTEM_FOUNDATION ); EXPECT_EQ( event->id, FOUNDATIONEVENT_FILE_DELETED ); EXPECT_STREQ( event->payload, filetestpath ); event = event_next( block, event ); EXPECT_EQ( event, 0 ); fs_unmonitor( testpath ); thread_sleep( 1000 ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_EQ( event, 0 ); stream_deallocate( fs_open_file( filetestpath, STREAM_OUT ) ); thread_sleep( 100 ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_EQ( event, 0 ); fs_remove_file( filetestpath ); thread_sleep( 100 ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_EQ( event, 0 ); fs_remove_directory( testpath ); string_deallocate( testpath ); string_deallocate( filetestpath ); return 0; }
DECLARE_TEST( fs, query ) { uint64_t subpathid = random64(); uint64_t subfileid = random64(); char* testpath = path_merge( environment_temporary_directory(), string_from_int_static( random64(), 0, 0 ) ); char* subtestpath = path_merge( testpath, string_from_int_static( subpathid, 0, 0 ) ); char* filepath[8]; char** subdirs; char** files; int ifp = 0; char* subfilepath; if( fs_is_file( testpath ) ) fs_remove_file( testpath ); if( !fs_is_directory( testpath ) ) fs_make_directory( testpath ); if( !fs_is_directory( subtestpath ) ) fs_make_directory( subtestpath ); for( ifp = 0; ifp < 8; ++ifp ) { filepath[ifp] = path_merge( testpath, string_from_int_static( random64(), 0, 0 ) ); filepath[ifp] = string_append( string_append( filepath[ifp], "." ), string_from_int_static( ifp, 0, 0 ) ); stream_deallocate( fs_open_file( filepath[ifp], STREAM_OUT ) ); } subfilepath = path_merge( subtestpath, string_from_int_static( subfileid, 0, 0 ) ); subfilepath = string_append( subfilepath, ".0" ); stream_deallocate( fs_open_file( subfilepath, STREAM_OUT ) ); files = fs_files( filepath[0] ); EXPECT_EQ( array_size( files ), 0 ); string_array_deallocate( files ); subdirs = fs_subdirs( subtestpath ); EXPECT_EQ( array_size( subdirs ), 0 ); string_array_deallocate( subdirs ); files = fs_files( testpath ); EXPECT_EQ( array_size( files ), 8 ); string_array_deallocate( files ); subdirs = fs_subdirs( testpath ); EXPECT_EQ( array_size( subdirs ), 1 ); string_array_deallocate( subdirs ); files = fs_matching_files( testpath, "*", false ); EXPECT_EQ( array_size( files ), 8 ); string_array_deallocate( files ); files = fs_matching_files( testpath, "*", true ); EXPECT_EQ( array_size( files ), 9 ); string_array_deallocate( files ); files = fs_matching_files( testpath, "*.0", false ); EXPECT_EQ( array_size( files ), 1 ); string_array_deallocate( files ); files = fs_matching_files( testpath, "*.0", true ); EXPECT_EQ( array_size( files ), 2 ); string_array_deallocate( files ); files = fs_matching_files( testpath, "*.1", false ); EXPECT_EQ( array_size( files ), 1 ); string_array_deallocate( files ); files = fs_matching_files( testpath, "*.1", true ); EXPECT_EQ( array_size( files ), 1 ); string_array_deallocate( files ); files = fs_matching_files( testpath, "*.?", true ); EXPECT_EQ( array_size( files ), 9 ); { char* verifypath = string_from_int( subpathid, 0, 0 ); verifypath = path_append( verifypath, string_from_int_static( subfileid, 0, 0 ) ); verifypath = string_append( verifypath, ".0" ); EXPECT_STREQ( files[8], verifypath ); string_deallocate( verifypath ); } string_array_deallocate( files ); fs_remove_directory( testpath ); string_array_deallocate( subdirs ); string_array_deallocate( files ); string_deallocate( subfilepath ); for( ifp = 0; ifp < 8; ++ifp ) string_deallocate( filepath[ifp] ); string_deallocate( subtestpath ); string_deallocate( testpath ); return 0; }
void config_load( const char* name, hash_t filter_section, bool built_in, bool overwrite ) { /*lint --e{838} Safety null assign all pointers for all preprocessor paths */ /*lint --e{750} Unused macros in some paths */ #define NUM_SEARCH_PATHS 10 #define ANDROID_ASSET_PATH_INDEX 5 char* sub_exe_path = 0; char* exe_parent_path = 0; char* exe_processed_path = 0; char* abs_exe_parent_path = 0; char* abs_exe_processed_path = 0; char* bundle_path = 0; char* home_dir = 0; char* cmdline_path = 0; char* cwd_config_path = 0; const char* paths[NUM_SEARCH_PATHS]; #if !FOUNDATION_PLATFORM_FAMILY_MOBILE const char* const* cmd_line; int icl, clsize; #endif int start_path, i, j; const char buildsuffix[4][9] = { "/debug", "/release", "/profile", "/deploy" }; const char platformsuffix[7][14] = { "/win32", "/win64", "/osx", "/ios", "/android", "/raspberrypi", "/unknown" }; const char binsuffix[1][5] = { "/bin" }; FOUNDATION_ASSERT( name ); sub_exe_path = path_merge( environment_executable_directory(), "config" ); exe_parent_path = path_merge( environment_executable_directory(), "../config" ); abs_exe_parent_path = path_make_absolute( exe_parent_path ); exe_processed_path = string_clone( environment_executable_directory() ); for( i = 0; i < 4; ++i ) { if( string_ends_with( exe_processed_path, buildsuffix[i] ) ) { exe_processed_path[ string_length( exe_processed_path ) - string_length( buildsuffix[i] ) ] = 0; break; } } for( i = 0; i < 7; ++i ) { if( string_ends_with( exe_processed_path, platformsuffix[i] ) ) { exe_processed_path[ string_length( exe_processed_path ) - string_length( platformsuffix[i] ) ] = 0; break; } } for( i = 0; i < 1; ++i ) { if( string_ends_with( exe_processed_path, binsuffix[i] ) ) { exe_processed_path[ string_length( exe_processed_path ) - string_length( binsuffix[i] ) ] = 0; break; } } exe_processed_path = path_append( exe_processed_path, "config" ); abs_exe_processed_path = path_make_absolute( exe_processed_path ); paths[0] = environment_executable_directory(); paths[1] = sub_exe_path; paths[2] = abs_exe_parent_path; paths[3] = abs_exe_processed_path; #if FOUNDATION_PLATFORM_FAMILY_DESKTOP && !BUILD_DEPLOY paths[4] = environment_initial_working_directory(); #else paths[4] = 0; #endif #if FOUNDATION_PLATFORM_APPLE bundle_path = path_merge( environment_executable_directory(), "../Resources/config" ); paths[5] = bundle_path; #elif FOUNDATION_PLATFORM_ANDROID paths[5] = "/config"; #else paths[5] = 0; #endif #if FOUNDATION_PLATFORM_FAMILY_DESKTOP paths[6] = environment_current_working_directory(); #else paths[6] = 0; #endif paths[7] = 0; paths[8] = 0; string_deallocate( exe_parent_path ); string_deallocate( exe_processed_path ); #if FOUNDATION_PLATFORM_FAMILY_DESKTOP cwd_config_path = path_merge( environment_current_working_directory(), "config" ); paths[7] = cwd_config_path; cmd_line = environment_command_line(); /*lint -e{850} We modify loop var to skip extra arg */ for( icl = 0, clsize = array_size( cmd_line ); icl < clsize; ++icl ) { /*lint -e{613} array_size( cmd_line ) in loop condition does the null pointer guard */ if( string_equal_substr( cmd_line[icl], "--configdir", 11 ) ) { if( string_equal_substr( cmd_line[icl], "--configdir=", 12 ) ) { paths[8] = cmdline_path = string_substr( cmd_line[icl], 12, STRING_NPOS ); } else if( icl < ( clsize - 1 ) ) { paths[8] = cmdline_path = string_clone( cmd_line[++icl] ); } } } #endif start_path = 0; if( !built_in ) { #if FOUNDATION_PLATFORM_WINDOWS home_dir = path_merge( environment_home_directory(), environment_application()->config_dir ); #elif FOUNDATION_PLATFORM_LINUX || FOUNDATION_PLATFORM_MACOSX home_dir = path_prepend( string_concat( ".", environment_application()->config_dir ), environment_home_directory() ); #endif if( home_dir ) paths[9] = home_dir; start_path = 9; } else { paths[9] = 0; } for( i = start_path; i < NUM_SEARCH_PATHS; ++i ) { char* filename; stream_t* istream; bool path_already_searched = false; if( !paths[i] ) continue; for( j = start_path; j < i; ++j ) { if( paths[j] && string_equal( paths[j], paths[i] ) ) { path_already_searched = true; break; } } if( path_already_searched ) continue; //TODO: Support loading configs from virtual file system (i.e in zip/other packages) filename = string_append( path_merge( paths[i], name ), ".ini" ); istream = 0; #if FOUNDATION_PLATFORM_ANDROID if( i == ANDROID_ASSET_PATH_INDEX ) istream = asset_stream_open( filename, STREAM_IN ); else #endif istream = stream_open( filename, STREAM_IN ); if( istream ) { config_parse( istream, filter_section, overwrite ); stream_deallocate( istream ); } string_deallocate( filename ); if( built_in ) { const char* FOUNDATION_PLATFORM_name = #if FOUNDATION_PLATFORM_WINDOWS "windows"; #elif FOUNDATION_PLATFORM_LINUX_RASPBERRYPI "raspberrypi"; #elif FOUNDATION_PLATFORM_LINUX "linux"; #elif FOUNDATION_PLATFORM_MACOSX "osx"; #elif FOUNDATION_PLATFORM_IOS "ios"; #elif FOUNDATION_PLATFORM_ANDROID "android"; #else # error Insert platform name "unknown"; #endif filename = string_append( path_append( path_merge( paths[i], FOUNDATION_PLATFORM_name ), name ), ".ini" ); #if FOUNDATION_PLATFORM_ANDROID if( i == ANDROID_ASSET_PATH_INDEX ) istream = asset_stream_open( filename, STREAM_IN ); else #endif istream = stream_open( filename, STREAM_IN ); if( istream ) { config_parse( istream, filter_section, overwrite ); stream_deallocate( istream ); } string_deallocate( filename ); } } string_deallocate( home_dir ); string_deallocate( cmdline_path ); string_deallocate( sub_exe_path ); string_deallocate( abs_exe_processed_path ); string_deallocate( abs_exe_parent_path ); string_deallocate( bundle_path ); string_deallocate( cwd_config_path ); }
char* path_make_temporary( void ) { char uintbuffer[18]; return path_merge( environment_temporary_directory(), string_from_uint_buffer( uintbuffer, random64(), true, 0, '0' ) ); }
int main_run( void* main_arg ) { const char* pattern = 0; char** exe_paths = 0; unsigned int iexe, exesize; process_t* process = 0; char* process_path = 0; int process_result = 0; object_t thread = 0; thread = thread_create( event_thread, "event_thread", THREAD_PRIORITY_NORMAL, 0 ); thread_start( thread, 0 ); #if FOUNDATION_PLATFORM_ANDROID int test_fn = 0; test_run_fn tests[] = { //test_app_run test_array_run, test_atomic_run, test_base64_run, test_bitbuffer_run, test_blowfish_run, test_bufferstream_run, test_config_run, test_crash_run, test_environment_run, test_error_run, test_event_run, test_fs_run, test_hash_run, test_hashmap_run, test_hashtable_run, test_library_run, test_math_run, test_md5_run, test_mutex_run, test_objectmap_run, test_path_run, test_pipe_run, test_profile_run, test_radixsort_run, test_random_run, test_ringbuffer_run, test_semaphore_run, //test_stacktrace_run, test_string_run, test_uuid_run, 0 }; do { if( process_result >= 0 ) { if( ( process_result = tests[test_fn]() ) >= 0 ) log_infof( HASH_TEST, "All tests passed (%d)", process_result ); } ++test_fn; } while( tests[test_fn] && ( process_result >= 0 ) ); if( process_result != 0 ) { log_warnf( HASH_TEST, WARNING_SUSPICIOUS, "Tests failed with exit code %d", process_result ); } #else //Find all test executables in the current executable directory #if FOUNDATION_PLATFORM_WINDOWS pattern = "test-*.exe"; #elif FOUNDATION_PLATFORM_MACOSX || FOUNDATION_PLATFORM_IOS pattern = "test-*"; #elif FOUNDATION_PLATFORM_POSIX pattern = "test-*"; #else # error Not implemented #endif exe_paths = fs_matching_files( environment_executable_directory(), pattern, true ); for( iexe = 0, exesize = array_size( exe_paths ); iexe < exesize; ++iexe ) { bool is_self = false; char* exe_file_name = path_base_file_name( exe_paths[iexe] ); if( string_equal( exe_file_name, environment_executable_name() ) ) is_self = true; string_deallocate( exe_file_name ); if( is_self ) continue; //Don't run self process_path = path_merge( environment_executable_directory(), exe_paths[iexe] ); process = process_allocate(); process_set_executable_path( process, process_path ); process_set_working_directory( process, environment_executable_directory() ); process_set_flags( process, PROCESS_ATTACHED ); log_infof( HASH_TEST, "Running test executable: %s", exe_paths[iexe] ); process_result = process_spawn( process ); while( process_result == PROCESS_WAIT_INTERRUPTED ) { thread_sleep( 10 ); process_result = process_wait( process ); } process_deallocate( process ); string_deallocate( process_path ); if( process_result != 0 ) { if( process_result >= PROCESS_INVALID_ARGS ) log_warnf( HASH_TEST, WARNING_SUSPICIOUS, "Tests failed, process terminated with error %x", process_result ); else log_warnf( HASH_TEST, WARNING_SUSPICIOUS, "Tests failed with exit code %d", process_result ); process_set_exit_code( -1 ); goto exit; } log_infof( HASH_TEST, "All tests from %s passed (%d)", exe_paths[iexe], process_result ); } log_info( HASH_TEST, "All tests passed" ); exit: if( exe_paths ) string_array_deallocate( exe_paths ); #endif thread_terminate( thread ); thread_destroy( thread ); while( thread_is_running( thread ) ) thread_sleep( 10 ); return process_result; }
int main_run( void* main_arg ) { #if !FOUNDATION_PLATFORM_IOS && !FOUNDATION_PLATFORM_ANDROID const char* pattern = 0; char** exe_paths = 0; unsigned int iexe, exesize; process_t* process = 0; char* process_path = 0; unsigned int* exe_flags = 0; #endif int process_result = 0; object_t thread = 0; log_set_suppress( HASH_TEST, ERRORLEVEL_DEBUG ); thread = thread_create( event_thread, "event_thread", THREAD_PRIORITY_NORMAL, 0 ); thread_start( thread, 0 ); while( !thread_is_running( thread ) ) thread_sleep( 10 ); #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID while( !_test_should_start ) thread_sleep( 10 ); test_run_fn tests[] = { //test_app_run test_array_run, test_atomic_run, test_base64_run, test_bitbuffer_run, test_blowfish_run, test_bufferstream_run, test_config_run, test_crash_run, test_environment_run, test_error_run, test_event_run, test_fs_run, test_hash_run, test_hashmap_run, test_hashtable_run, test_library_run, test_math_run, test_md5_run, test_mutex_run, test_objectmap_run, test_path_run, test_pipe_run, test_profile_run, test_radixsort_run, test_random_run, test_ringbuffer_run, test_semaphore_run, test_stacktrace_run, test_string_run, test_uuid_run, 0 }; #if FOUNDATION_PLATFORM_ANDROID object_t test_thread = thread_create( test_runner, "test_runner", THREAD_PRIORITY_NORMAL, 0 ); thread_start( test_thread, tests ); while( !thread_is_running( test_thread ) ) { system_process_events(); thread_sleep( 10 ); } while( thread_is_running( test_thread ) ) { system_process_events(); thread_sleep( 10 ); } process_result = (int)(intptr_t)thread_result( test_thread ); thread_destroy( test_thread ); while( thread_is_thread( test_thread ) ) { system_process_events(); thread_sleep( 10 ); } #else process_result = (int)(intptr_t)test_runner( 0, tests ); #endif if( process_result != 0 ) log_warnf( HASH_TEST, WARNING_SUSPICIOUS, "Tests failed with exit code %d", process_result ); while( !_test_should_terminate ) { system_process_events(); thread_sleep( 100 ); } log_debug( HASH_TEST, "Exiting main loop" ); #else //Find all test executables in the current executable directory #if FOUNDATION_PLATFORM_WINDOWS pattern = "test-*.exe"; #elif FOUNDATION_PLATFORM_MACOSX pattern = "test-*"; #elif FOUNDATION_PLATFORM_POSIX pattern = "test-*"; #else # error Not implemented #endif exe_paths = fs_matching_files( environment_executable_directory(), pattern, false ); array_resize( exe_flags, array_size( exe_paths ) ); memset( exe_flags, 0, sizeof( unsigned int ) * array_size( exe_flags ) ); #if FOUNDATION_PLATFORM_MACOSX //Also search for test-*.app const char* app_pattern = "test-*.app"; char** subdirs = fs_subdirs( environment_executable_directory() ); for( int idir = 0, dirsize = array_size( subdirs ); idir < dirsize; ++idir ) { if( string_match_pattern( subdirs[idir], app_pattern ) ) { array_push( exe_paths, string_substr( subdirs[idir], 0, string_length( subdirs[idir] ) - 4 ) ); array_push( exe_flags, PROCESS_OSX_USE_OPENAPPLICATION ); } } string_array_deallocate( subdirs ); #endif for( iexe = 0, exesize = array_size( exe_paths ); iexe < exesize; ++iexe ) { bool is_self = false; char* exe_file_name = path_base_file_name( exe_paths[iexe] ); if( string_equal( exe_file_name, environment_executable_name() ) ) is_self = true; string_deallocate( exe_file_name ); if( is_self ) continue; //Don't run self process_path = path_merge( environment_executable_directory(), exe_paths[iexe] ); process = process_allocate(); process_set_executable_path( process, process_path ); process_set_working_directory( process, environment_executable_directory() ); process_set_flags( process, PROCESS_ATTACHED | exe_flags[iexe] ); log_infof( HASH_TEST, "Running test executable: %s", exe_paths[iexe] ); process_result = process_spawn( process ); while( process_result == PROCESS_WAIT_INTERRUPTED ) { thread_sleep( 10 ); process_result = process_wait( process ); } process_deallocate( process ); string_deallocate( process_path ); if( process_result != 0 ) { if( process_result >= PROCESS_INVALID_ARGS ) log_warnf( HASH_TEST, WARNING_SUSPICIOUS, "Tests failed, process terminated with error %x", process_result ); else log_warnf( HASH_TEST, WARNING_SUSPICIOUS, "Tests failed with exit code %d", process_result ); process_set_exit_code( -1 ); goto exit; } log_infof( HASH_TEST, "All tests from %s passed (%d)", exe_paths[iexe], process_result ); } log_info( HASH_TEST, "All tests passed" ); exit: if( exe_paths ) string_array_deallocate( exe_paths ); array_deallocate( exe_flags ); #endif thread_terminate( thread ); thread_destroy( thread ); while( thread_is_running( thread ) ) thread_sleep( 10 ); while( thread_is_thread( thread ) ) thread_sleep( 10 ); return process_result; }