DECLARE_TEST( environment, builtin ) { char const* const* cmdline = environment_command_line(); EXPECT_GE( array_size( cmdline ), 1 ); #if !FOUNDATION_PLATFORM_ANDROID && !FOUNDATION_PLATFORM_IOS EXPECT_NE( string_find_string( cmdline[0], "test-environment", 0 ), STRING_NPOS ); EXPECT_STREQ( environment_executable_name(), "test-environment" ); #endif EXPECT_NE( environment_initial_working_directory(), 0 ); EXPECT_NE( string_length( environment_initial_working_directory() ), 0 ); EXPECT_STREQ( environment_initial_working_directory(), environment_current_working_directory() ); EXPECT_NE( environment_home_directory(), 0 ); EXPECT_NE( string_length( environment_home_directory() ), 0 ); EXPECT_NE( environment_temporary_directory(), 0 ); EXPECT_NE( string_length( environment_temporary_directory() ), 0 ); EXPECT_NE( environment_variable( "PATH" ), 0 ); EXPECT_NE( string_length( environment_variable( "PATH" ) ), 0 ); return 0; }
DECLARE_TEST(environment, builtin) { const string_const_t* cmdline = environment_command_line(); EXPECT_GE(array_size(cmdline), 1); #if !BUILD_MONOLITHIC EXPECT_NE_MSGFORMAT(string_find_string(STRING_ARGS(cmdline[0]), STRING_CONST("test-environment"), 0), STRING_NPOS, "Commandline: %.*s", (int)cmdline[0].length, cmdline[0].str); EXPECT_CONSTSTRINGEQ(environment_executable_name(), string_const(STRING_CONST("test-environment"))); #elif FOUNDATION_PLATFORM_ANDROID EXPECT_NE_MSGFORMAT(string_find_string(STRING_ARGS(cmdline[0]), STRING_CONST("com.rampantpixels.foundation.test"), 0), STRING_NPOS, "Commandline: %.*s", (int)cmdline[0].length, cmdline[0].str); #elif !FOUNDATION_PLATFORM_PNACL EXPECT_NE_MSGFORMAT(string_find_string(STRING_ARGS(cmdline[0]), STRING_CONST("test-all"), 0), STRING_NPOS, "Commandline: %.*s", (int)cmdline[0].length, cmdline[0].str); EXPECT_CONSTSTRINGEQ(environment_executable_name(), string_const(STRING_CONST("test-all"))); #endif EXPECT_NE(environment_initial_working_directory().str, 0); EXPECT_NE(environment_initial_working_directory().length, 0); EXPECT_CONSTSTRINGEQ(environment_initial_working_directory(), environment_current_working_directory()); EXPECT_NE(environment_home_directory().str, 0); EXPECT_NE(environment_home_directory().length, 0); EXPECT_NE(environment_temporary_directory().str, 0); EXPECT_NE(environment_temporary_directory().length, 0); #if !FOUNDATION_PLATFORM_PNACL EXPECT_NE(environment_variable(STRING_CONST("PATH")).str, 0); EXPECT_NE(environment_variable(STRING_CONST("PATH")).length, 0); #endif return 0; }
DECLARE_TEST( environment, builtin ) { char const* const* cmdline = environment_command_line(); EXPECT_GE( array_size( cmdline ), 1 ); #if !BUILD_MONOLITHIC EXPECT_NE_MSGFORMAT( string_find_string( cmdline[0], "test-environment", 0 ), STRING_NPOS, "Commandline: %s", cmdline[0] ); EXPECT_STREQ( environment_executable_name(), "test-environment" ); #elif FOUNDATION_PLATFORM_ANDROID EXPECT_NE_MSGFORMAT( string_find_string( cmdline[0], "com.rampantpixels.foundation.test", 0 ), STRING_NPOS, "Commandline: %s", cmdline[0] ); #elif !FOUNDATION_PLATFORM_PNACL EXPECT_NE_MSGFORMAT( string_find_string( cmdline[0], "test-all", 0 ), STRING_NPOS, "Commandline: %s", cmdline[0] ); EXPECT_STREQ( environment_executable_name(), "test-all" ); #endif EXPECT_NE( environment_initial_working_directory(), 0 ); EXPECT_NE( string_length( environment_initial_working_directory() ), 0 ); EXPECT_STREQ( environment_initial_working_directory(), environment_current_working_directory() ); EXPECT_NE( environment_home_directory(), 0 ); EXPECT_NE( string_length( environment_home_directory() ), 0 ); EXPECT_NE( environment_temporary_directory(), 0 ); EXPECT_NE( string_length( environment_temporary_directory() ), 0 ); #if !FOUNDATION_PLATFORM_PNACL EXPECT_NE( environment_variable( "PATH" ), 0 ); EXPECT_NE( string_length( environment_variable( "PATH" ) ), 0 ); #endif return 0; }
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; }
static NOINLINE const char* _expand_environment( hash_t key, char* var ) { if( key == HASH_EXECUTABLE_NAME ) return environment_executable_name(); else if( key == HASH_EXECUTABLE_DIRECTORY ) return environment_executable_directory(); else if( key == HASH_EXECUTABLE_PATH ) return environment_executable_path(); else if( key == HASH_INITIAL_WORKING_DIRECTORY ) return environment_initial_working_directory(); else if( key == HASH_CURRENT_WORKING_DIRECTORY ) return environment_current_working_directory(); else if( key == HASH_HOME_DIRECTORY ) return environment_home_directory(); else if( key == HASH_TEMPORARY_DIRECTORY ) return environment_temporary_directory(); else if( string_equal_substr( var, "variable[", 9 ) ) //variable[varname] - Environment variable named "varname" { const char* value; unsigned int end_pos = string_find( var, ']', 9 ); if( end_pos != STRING_NPOS ) var[end_pos] = 0; value = environment_variable( var ); if( end_pos != STRING_NPOS ) var[end_pos] = ']'; return value; } return ""; }
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; }
int main_run(void* main_arg) { #if !BUILD_MONOLITHIC string_const_t pattern; string_t* exe_paths = 0; size_t iexe, exesize; process_t* process = 0; string_t process_path = { 0, 0 }; unsigned int* exe_flags = 0; #else void* test_result; #endif #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID || FOUNDATION_PLATFORM_PNACL int remain_counter = 0; #endif #if BUILD_DEBUG const string_const_t build_name = string_const(STRING_CONST("debug")); #elif BUILD_RELEASE const string_const_t build_name = string_const(STRING_CONST("release")); #elif BUILD_PROFILE const string_const_t build_name = string_const(STRING_CONST("profile")); #elif BUILD_DEPLOY const string_const_t build_name = string_const(STRING_CONST("deploy")); #endif #if BUILD_MONOLITHIC const string_const_t build_type = string_const(STRING_CONST(" monolithic")); #else const string_const_t build_type = string_empty(); #endif char* pathbuf; int process_result = 0; thread_t event_thread; FOUNDATION_UNUSED(main_arg); FOUNDATION_UNUSED(build_name); log_set_suppress(HASH_TEST, ERRORLEVEL_DEBUG); log_infof(HASH_TEST, STRING_CONST("Task library v%s built for %s using %s (%.*s%.*s)"), string_from_version_static(task_module_version()).str, FOUNDATION_PLATFORM_DESCRIPTION, FOUNDATION_COMPILER_DESCRIPTION, STRING_FORMAT(build_name), STRING_FORMAT(build_type)); thread_initialize(&event_thread, event_loop, 0, STRING_CONST("event_thread"), THREAD_PRIORITY_NORMAL, 0); thread_start(&event_thread); pathbuf = memory_allocate(HASH_STRING, BUILD_MAX_PATHLEN, 0, MEMORY_PERSISTENT); while (!thread_is_running(&event_thread)) thread_sleep(10); #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID || FOUNDATION_PLATFORM_PNACL while (!_test_should_start) { #if FOUNDATION_PLATFORM_ANDROID system_process_events(); #endif thread_sleep(100); } #endif fs_remove_directory(STRING_ARGS(environment_temporary_directory())); #if BUILD_MONOLITHIC test_run_fn tests[] = { test_task_run, 0 }; #if FOUNDATION_PLATFORM_ANDROID thread_t test_thread; thread_initialize(&test_thread, test_runner, tests, STRING_CONST("test_runner"), THREAD_PRIORITY_NORMAL, 0); thread_start(&test_thread); log_debug(HASH_TEST, STRING_CONST("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); } test_result = thread_join(&test_thread); process_result = (int)(intptr_t)test_result; thread_finalize(&test_thread); #else test_result = test_runner(tests); process_result = (int)(intptr_t)test_result; #endif if (process_result != 0) log_warnf(HASH_TEST, WARNING_SUSPICIOUS, STRING_CONST("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, STRING_CONST("Exiting main loop")); #else // !BUILD_MONOLITHIC //Find all test executables in the current executable directory #if FOUNDATION_PLATFORM_WINDOWS pattern = string_const(STRING_CONST("^test-.*\\.exe$")); #elif FOUNDATION_PLATFORM_MACOSX pattern = string_const(STRING_CONST("^test-.*$")); #elif FOUNDATION_PLATFORM_POSIX pattern = string_const(STRING_CONST("^test-.*$")); #else # error Not implemented #endif exe_paths = fs_matching_files(STRING_ARGS(environment_executable_directory()), STRING_ARGS(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 string_const_t app_pattern = string_const(STRING_CONST("^test-.*\\.app$")); regex_t* app_regex = regex_compile(app_pattern.str, app_pattern.length); string_t* subdirs = fs_subdirs(STRING_ARGS(environment_executable_directory())); for (size_t idir = 0, dirsize = array_size(subdirs); idir < dirsize; ++idir) { if (regex_match(app_regex, subdirs[idir].str, subdirs[idir].length, 0, 0)) { string_t exe_path = { subdirs[idir].str, subdirs[idir].length - 4 }; array_push(exe_paths, exe_path); 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) { string_const_t* process_args = 0; string_const_t exe_file_name = path_base_file_name(STRING_ARGS(exe_paths[iexe])); if (string_equal(STRING_ARGS(exe_file_name), STRING_ARGS(environment_executable_name()))) continue; //Don't run self process_path = path_concat(pathbuf, BUILD_MAX_PATHLEN, STRING_ARGS(environment_executable_directory()), STRING_ARGS(exe_paths[iexe])); process = process_allocate(); process_set_executable_path(process, STRING_ARGS(process_path)); process_set_working_directory(process, STRING_ARGS(environment_executable_directory())); process_set_flags(process, PROCESS_ATTACHED | exe_flags[iexe]); if (!_test_memory_tracker) array_push(process_args, string_const(STRING_CONST("--no-memory-tracker"))); process_set_arguments(process, process_args, array_size(process_args)); log_infof(HASH_TEST, STRING_CONST("Running test executable: %.*s"), STRING_FORMAT(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); array_deallocate(process_args); if (process_result != 0) { if (process_result >= PROCESS_INVALID_ARGS) log_warnf(HASH_TEST, WARNING_SUSPICIOUS, STRING_CONST("Tests failed, process terminated with error %x"), process_result); else log_warnf(HASH_TEST, WARNING_SUSPICIOUS, STRING_CONST("Tests failed with exit code %d"), process_result); process_set_exit_code(-1); goto exit; } log_infof(HASH_TEST, STRING_CONST("All tests from %.*s passed (%d)"), STRING_FORMAT(exe_paths[iexe]), process_result); } log_info(HASH_TEST, STRING_CONST("All tests passed")); exit: if (exe_paths) string_array_deallocate(exe_paths); array_deallocate(exe_flags); #endif _test_should_terminate = true; thread_signal(&event_thread); thread_finalize(&event_thread); memory_deallocate(pathbuf); log_infof(HASH_TEST, STRING_CONST("Tests exiting: %s (%d)"), process_result ? "FAILED" : "PASSED", process_result); if (process_result) memory_set_tracker(memory_tracker_none()); return process_result; }
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(profile, stream) { thread_t thread[32]; int ith; uint64_t frame; string_t filename; error(); //Clear error filename = path_allocate_concat(STRING_ARGS(environment_temporary_directory()), STRING_CONST("test.profile")); //log_infof(HASH_TEST, STRING_CONST("Output to profile file: %.*s"), STRING_FORMAT(filename)); fs_make_directory(STRING_ARGS(environment_temporary_directory())); _profile_stream = fs_open_file(STRING_ARGS(filename), STREAM_OUT | STREAM_BINARY); string_deallocate(filename.str); profile_initialize(STRING_CONST("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_initialize(&thread[ith], _profile_stream_thread, 0, STRING_CONST("profile_thread"), THREAD_PRIORITY_NORMAL, 0); for (ith = 0; ith < 32; ++ith) thread_start(&thread[ith]); test_wait_for_threads_startup(thread, 32); for (frame = 0; frame < 1000; ++frame) { thread_sleep(16); profile_log( STRING_CONST("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_signal(&thread[ith]); test_wait_for_threads_finish(thread, 32); for (ith = 0; ith < 32; ++ith) thread_finalize(&thread[ith]); profile_end_frame(frame++); profile_set_output_wait(10000); thread_sleep(1000); profile_begin_block(STRING_CONST("Should be cleaned up")); profile_end_block(); profile_enable(false); profile_finalize(); error(); stream_deallocate(_profile_stream); //TODO: Validate that output is sane log_debugf(HASH_TEST, STRING_CONST("Generated %" PRId64 " 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; }
int _environment_initialize( const application_t application ) { #if FOUNDATION_PLATFORM_WINDOWS int ia; int num_args = 0; DWORD ret = 0; wchar_t module_filename[FOUNDATION_MAX_PATHLEN]; LPWSTR* arg_list = CommandLineToArgvW( GetCommandLineW(), &num_args ); if( !arg_list ) return -1; for( ia = 0; ia < num_args; ++ia ) array_push( _environment_argv, string_allocate_from_wstring( arg_list[ia], 0 ) ); LocalFree( arg_list ); if( GetModuleFileNameW( 0, module_filename, FOUNDATION_MAX_PATHLEN ) ) { char* exe_path = string_allocate_from_wstring( module_filename, 0 ); char* dir_path = path_make_absolute( exe_path ); _environment_set_executable_paths( dir_path ); string_deallocate( dir_path ); string_deallocate( exe_path ); } else { log_errorf( ERROR_SYSTEM_CALL_FAIL, "Unable to get module filename" ); return -1; } #elif FOUNDATION_PLATFORM_APPLE int ia; int* argc_ptr = _NSGetArgc(); char*** argv_ptr = _NSGetArgv(); for( ia = 0; ia < *argc_ptr; ++ia ) array_push( _environment_argv, string_clone( (*argv_ptr)[ia] ) ); FOUNDATION_ASSERT( *argc_ptr > 0 ); char* exe_path = path_make_absolute( (*argv_ptr)[0] ); _environment_set_executable_paths( exe_path ); string_deallocate( exe_path ); #elif FOUNDATION_PLATFORM_POSIX stream_t* cmdline = fs_open_file( "/proc/self/cmdline", STREAM_IN | STREAM_BINARY ); if( !cmdline ) { log_errorf( ERROR_SYSTEM_CALL_FAIL, "Unable to read /proc/self/cmdline" ); return -1; } while( true ) { char* arg = stream_read_string( cmdline ); if( !string_length( arg ) ) { string_deallocate( arg ); break; } array_push( _environment_argv, arg ); } char exelink[FOUNDATION_MAX_PATHLEN] = {0}; if( readlink( "/proc/self/exe", exelink, FOUNDATION_MAX_PATHLEN ) < 0 ) { log_errorf( ERROR_SYSTEM_CALL_FAIL, "Unable to read /proc/self/exe link" ); return -1; } char* exe_path; char* dir_path; exe_path = path_clean( string_clone( exelink ), path_is_absolute( exelink ) ); dir_path = path_make_absolute( exe_path ); _environment_set_executable_paths( dir_path ); string_deallocate( dir_path ); string_deallocate( exe_path ); #else # error Not implemented /*if( array_size( _environment_argv ) > 0 ) { char* exe_path = path_clean( string_clone( _environment_argv[0] ), path_is_absolute( _environment_argv[0] ) ); char* dir_path = path_make_absolute( exe_path ); _environment_set_executable_paths( dir_path ); string_deallocate( dir_path ); string_deallocate( exe_path ); } else if( !string_length( _environment_executable_dir ) ) string_copy( _environment_executable_dir, environment_current_working_directory(), FOUNDATION_MAX_PATHLEN ); */ #endif _environment_app = application; if( uuid_is_null( _environment_app.instance ) ) _environment_app.instance = uuid_generate_random(); string_copy( _environment_initial_working_dir, environment_current_working_directory(), FOUNDATION_MAX_PATHLEN ); environment_temporary_directory(); return 0; }
char* path_make_temporary( void ) { char uintbuffer[18]; return path_merge( environment_temporary_directory(), string_from_uint_buffer( uintbuffer, random64(), true, 0, '0' ) ); }