示例#1
0
void
process_set_arguments(process_t* proc, const string_const_t* args, size_t num) {
	size_t ia;
	string_array_deallocate(proc->args);
	for (ia = 0; ia < num; ++ia)
		array_push(proc->args, string_clone(args[ia].str, args[ia].length));
}
void _environment_shutdown( void )
{
	string_array_deallocate( _environment_argv );

#if FOUNDATION_PLATFORM_WINDOWS
	string_deallocate( _environment_var );
#endif
}
示例#3
0
void process_set_arguments( process_t* proc, const char** args, unsigned int num )
{
	unsigned int ia;
	if( !proc )
		return;
	string_array_deallocate( proc->args );
	for( ia = 0; ia < num; ++ia )
		array_push( proc->args, string_clone( args[ia] ) );
}
示例#4
0
int main_run( void* main_arg )
{
	int result = 0;
	hashify_input_t input = hashify_parse_command_line( environment_command_line() );
	
	result = hashify_process_strings( (char const* const*)input.strings );
	if( result < 0 )
		goto exit;

	result = hashify_process_files( (char const* const*)input.files, input.check_only );
	if( result < 0 )
		goto exit;

exit:

	string_array_deallocate( input.strings );
	string_array_deallocate( input.files );

	return result;
}
示例#5
0
int main_run( void* main_arg )
{
    int result = BIN2HEX_RESULT_OK;

    bin2hex_input_t input = bin2hex_parse_command_line( environment_command_line() );

    if( !array_size( input.input_files ) )
        bin2hex_print_usage();
    else
    {
        result = bin2hex_process_files( (char const* const*)input.input_files, (char const* const*)input.output_files, input.columns );
        if( result < 0 )
            goto exit;
    }

exit:

    string_array_deallocate( input.input_files );
    string_array_deallocate( input.output_files );

    return result;
}
示例#6
0
int hashify_read_hashes( stream_t* file, hashify_string_t** hashes )
{
	//Read in hashes in file
	char* line;
	char line_buffer[HASHIFY_LINEBUFFER_LENGTH];

	do
	{
		stream_read_line_buffer( file, line_buffer, HASHIFY_LINEBUFFER_LENGTH-1, '\n' );
		line = string_strip( line_buffer, "\n\r" );
		if( ( string_find_string( line, "define", 0 ) != STRING_NPOS ) && ( string_find_string( line, "static_hash", 0 ) != STRING_NPOS ) )
		{
			//Format is: #define HASH_<hashstring> static_hash_string( "<string>", 0x<hashvalue>ULL )
			char** tokens = string_explode( line, " \t", false );

			if( array_size( tokens ) >= 6 )
			{
				hashify_string_t hash_string;

				string_copy( hash_string.string, string_strip( string_strip( tokens[3], "," ), "\"" ), HASHIFY_STRING_LENGTH );
				hash_string.hash = string_to_uint64( tokens[4], true );

				if( hash( hash_string.string, string_length( hash_string.string ) ) != hash_string.hash )
				{
					log_errorf( ERROR_INVALID_VALUE, "  hash output file is out of date, %s is set to 0x%llx but should be 0x%llx ", hash_string.string, hash_string.hash, hash( hash_string.string, string_length( hash_string.string ) ) );
					string_array_deallocate( tokens );
					return HASHIFY_RESULT_OUTPUT_FILE_OUT_OF_DATE;
				}

				array_push_memcpy( *hashes, &hash_string );
			}

			string_array_deallocate( tokens );
		}
	} while( !stream_eos( file ) );

	return 0;
}
示例#7
0
void
process_finalize(process_t* proc) {
	if (!(proc->flags & PROCESS_DETACHED))
		process_wait(proc);

	stream_deallocate(proc->pipeout);
	stream_deallocate(proc->pipein);
	string_deallocate(proc->wd.str);
	string_deallocate(proc->path.str);
	string_array_deallocate(proc->args);
#if FOUNDATION_PLATFORM_WINDOWS
	string_deallocate(proc->verb.str);
#endif
}
示例#8
0
void process_deallocate( process_t* proc )
{
	if( !proc )
		return;
	if( !( proc->flags & PROCESS_DETACHED ) )
		process_wait( proc );
	stream_deallocate( proc->pipeout );
	stream_deallocate( proc->pipein );
	string_deallocate( proc->wd );
	string_deallocate( proc->path );
	string_array_deallocate( proc->args );
#if FOUNDATION_PLATFORM_WINDOWS
	string_deallocate( proc->verb );
#endif
	memory_deallocate( proc );
}
示例#9
0
char* stacktrace_resolve( void** trace, unsigned int max_depth, unsigned int skip_frames )
{
	char** lines;
	char* resolved;

	_initialize_symbol_resolve();
	
	if( !max_depth )
		max_depth = BUILD_SIZE_STACKTRACE_DEPTH;
	if( max_depth + skip_frames > BUILD_SIZE_STACKTRACE_DEPTH )
		max_depth = BUILD_SIZE_STACKTRACE_DEPTH - skip_frames;

	lines = _resolve_stack_frames( trace + skip_frames, max_depth );

	resolved = string_merge( (const char* const*)lines, array_size( lines ), "\n" );

	string_array_deallocate( lines );

	return resolved;
}
示例#10
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;
}
示例#11
0
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;
}
示例#12
0
DECLARE_TEST( string, utility )
{
	{
		char* path1 = string_clone( "" );
		char* path2 = string_clone( "/" );
		char* path3 = string_clone( "/." );
		char* path4 = string_clone( "./" );
		char* path5 = string_clone( "./." );
		char* path6 = string_clone( "././" );
		char* path7 = string_clone( "././//" );
		char* path8 = string_clone( "././//./////././////.//////.//." );
		char* path9 = string_clone( "http://././//./////././////.//////.//." );
		char* path10 = string_clone( "" );
		char* path11 = string_clone( "\\" );
		char* path12 = string_clone( "/\\." );
		char* path13 = string_clone( ".\\/" );
		char* path14 = string_clone( "./\\." );
		char* path15 = string_clone( ".\\.//\\" );
		char* path16 = string_clone( ".\\.\\\\\\" );
		char* path17 = string_clone( ".\\.\\\\\\.\\\\////\\///\\\\.\\.\\\\\\\\\\.\\\\\\\\\\\\.\\\\." );
		char* path18 = string_clone( "http://\\.\\.\\\\\\.\\\\\\\\//\\.\\.\\\\\\\\//\\.\\\\\\\\\\\\.\\\\." );
		
		char* path19 = string_clone( "testing/path/ext" );
		char* path20 = string_clone( "testing/path/extend" );
		char* path21 = string_clone( "testing/path/extend/dyn" );
		char* path22 = string_clone( "testing/./\\\\/\\/./path/././//./extend/\\\\" );

		path1 = path_clean( path1, true );
		path2 = path_clean( path2, true );
		path3 = path_clean( path3, true );
		path4 = path_clean( path4, true );
		path5 = path_clean( path5, true );
		path6 = path_clean( path6, true );
		path7 = path_clean( path7, true );
		path8 = path_clean( path8, true );
		path9 = path_clean( path9, true );
		path10 = path_clean( path10, true );
		path11 = path_clean( path11, true );
		path12 = path_clean( path12, true );
		path13 = path_clean( path13, true );
		path14 = path_clean( path14, true );
		path15 = path_clean( path15, true );
		path16 = path_clean( path16, true );
		path17 = path_clean( path17, true );
		path18 = path_clean( path18, true );
		path19 = path_clean( path19, true );
		path20 = path_clean( path20, true );
		path21 = path_clean( path21, true );
		path22 = path_clean( path22, true );

		EXPECT_TRUE( string_equal( path1, "/" ) );
		EXPECT_TRUE( string_equal( path2, "/" ) );
		EXPECT_TRUE( string_equal( path3, "/" ) );
		EXPECT_TRUE( string_equal( path4, "/" ) );
		EXPECT_TRUE( string_equal( path5, "/" ) );
		EXPECT_TRUE( string_equal( path6, "/" ) );
		EXPECT_TRUE( string_equal( path7, "/" ) );
		EXPECT_TRUE( string_equal( path8, "/" ) );
		EXPECT_TRUE( string_equal( path9, "http://" ) );
		EXPECT_TRUE( string_equal( path10, "/" ) );
		EXPECT_TRUE( string_equal( path11, "/" ) );
		EXPECT_TRUE( string_equal( path12, "/" ) );
		EXPECT_TRUE( string_equal( path13, "/" ) );
		EXPECT_TRUE( string_equal( path14, "/" ) );
		EXPECT_TRUE( string_equal( path15, "/" ) );
		EXPECT_TRUE( string_equal( path16, "/" ) );
		EXPECT_TRUE( string_equal( path17, "/" ) );
		EXPECT_TRUE( string_equal( path18, "http://" ) );
		EXPECT_TRUE( string_equal( path19, "/testing/path/ext" ) );
		EXPECT_TRUE( string_equal( path20, "/testing/path/extend" ) );
		EXPECT_TRUE( string_equal( path21, "/testing/path/extend/dyn" ) );
		EXPECT_TRUE( string_equal( path22, "/testing/path/extend" ) );

		string_deallocate( path1 );
		string_deallocate( path2 );
		string_deallocate( path3 );
		string_deallocate( path4 );
		string_deallocate( path5 );
		string_deallocate( path6 );
		string_deallocate( path7 );
		string_deallocate( path8 );
		string_deallocate( path9 );
		string_deallocate( path10 );
		string_deallocate( path11 );
		string_deallocate( path12 );
		string_deallocate( path13 );
		string_deallocate( path14 );
		string_deallocate( path15 );
		string_deallocate( path16 );
		string_deallocate( path17 );
		string_deallocate( path18 );
		string_deallocate( path19 );
		string_deallocate( path20 );
		string_deallocate( path21 );
		string_deallocate( path22 );
	}
	{
		char** explodearr = 0;
		char* explodestr = string_clone( "  .,testing,    .,utility.,string  methods ..., like,,,finds  split..merge     .,.explode.and. .., ., similar   .,,,. " );
		
		char* mergestr = string_clone( "    testing   merge string   " );
		char* mergestr2 = string_clone( " ., testing, .merge.string,. " );
		char* merged = 0;
		char** mergearr, **mergearr2, **mergearr3;

		char* splitstr = string_clone( " testing split" );
		char* splitright = 0, *splitleft = 0;
		char* splitright2 = 0, *splitleft2 = 0;

		char* substrtest = string_clone( "testing substr" );
		char* substr = 0;
		
		explodearr = string_explode( explodestr, " ,.", false );
		mergearr = string_explode( mergestr, " .,", true );
		mergearr2 = string_explode( mergestr, " .,", false );
		mergearr3 = string_explode( mergestr, " .,", true );
		merged = string_merge( (const char* const*)mergearr, array_size( mergearr ), " " );

		string_split( splitstr, " ", &splitleft, &splitright, false );
		string_split( splitstr, " ", &splitleft2, &splitright2, true );
		
		EXPECT_EQ( array_size( explodearr ), 11 );
		EXPECT_TRUE( string_equal( explodearr[0], "testing" ) );
		EXPECT_TRUE( string_equal( explodearr[1], "utility" ) );
		EXPECT_TRUE( string_equal( explodearr[2], "string" ) );
		EXPECT_TRUE( string_equal( explodearr[3], "methods" ) );
		EXPECT_TRUE( string_equal( explodearr[4], "like" ) );
		EXPECT_TRUE( string_equal( explodearr[5], "finds" ) );
		EXPECT_TRUE( string_equal( explodearr[6], "split" ) );
		EXPECT_TRUE( string_equal( explodearr[7], "merge" ) );
		EXPECT_TRUE( string_equal( explodearr[8], "explode" ) );
		EXPECT_TRUE( string_equal( explodearr[9], "and" ) );
		EXPECT_TRUE( string_equal( explodearr[10], "similar" ) );

		EXPECT_EQ( array_size( mergearr ), 12 );
		EXPECT_TRUE( string_equal( mergearr[0], "" ) );
		EXPECT_TRUE( string_equal( mergearr[1], "" ) );
		EXPECT_TRUE( string_equal( mergearr[2], "" ) );
		EXPECT_TRUE( string_equal( mergearr[3], "" ) );
		EXPECT_TRUE( string_equal( mergearr[4], "testing" ) );
		EXPECT_TRUE( string_equal( mergearr[5], "" ) );
		EXPECT_TRUE( string_equal( mergearr[6], "" ) );
		EXPECT_TRUE( string_equal( mergearr[7], "merge" ) );
		EXPECT_TRUE( string_equal( mergearr[8], "string" ) );
		EXPECT_TRUE( string_equal( mergearr[9], "" ) );
		EXPECT_TRUE( string_equal( mergearr[10], "" ) );
		EXPECT_TRUE( string_equal( mergearr[11], "" ) );

		EXPECT_EQ( array_size( mergearr2 ), 3 );
		EXPECT_TRUE( string_equal( mergearr2[0], "testing" ) );
		EXPECT_TRUE( string_equal( mergearr2[1], "merge" ) );
		EXPECT_TRUE( string_equal( mergearr2[2], "string" ) );
		EXPECT_TRUE( string_equal( merged, mergestr ) );

		EXPECT_EQ( array_size( mergearr3 ), 12 );
		EXPECT_TRUE( string_equal( mergearr3[0], "" ) );
		EXPECT_TRUE( string_equal( mergearr3[1], "" ) );
		EXPECT_TRUE( string_equal( mergearr3[2], "" ) );
		EXPECT_TRUE( string_equal( mergearr3[3], "" ) );
		EXPECT_TRUE( string_equal( mergearr3[4], "testing" ) );
		EXPECT_TRUE( string_equal( mergearr3[5], "" ) );
		EXPECT_TRUE( string_equal( mergearr3[6], "" ) );
		EXPECT_TRUE( string_equal( mergearr3[7], "merge" ) );
		EXPECT_TRUE( string_equal( mergearr3[8], "string" ) );
		EXPECT_TRUE( string_equal( mergearr3[9], "" ) );
		EXPECT_TRUE( string_equal( mergearr3[10], "" ) );
		EXPECT_TRUE( string_equal( mergearr3[11], "" ) );

		EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 0, 4 ), "test" ) ); string_deallocate( substr );
		EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 0, 14 ), "testing substr" ) ); string_deallocate( substr );
		EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 0, 20 ), "testing substr" ) ); string_deallocate( substr );
		EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 3, 20 ), "ting substr" ) ); string_deallocate( substr );
		EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 3, 11 ), "ting substr" ) ); string_deallocate( substr );
		EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 3, 1 ), "t" ) ); string_deallocate( substr );
		EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 3, 0 ), "" ) ); string_deallocate( substr );
		EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 20, 0 ), "" ) ); string_deallocate( substr );
		EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 20, 20 ), "" ) ); string_deallocate( substr );

		EXPECT_TRUE( string_equal( splitleft, "testing" ) );
		EXPECT_TRUE( string_equal( splitright, "split" ) );
		EXPECT_TRUE( string_equal( splitleft2, "" ) );
		EXPECT_TRUE( string_equal( splitright2, "testing split" ) );
		{
			char* replacestr = string_clone( "testing replace" );
			char* replacestr2 = string_clone( "testing replace" );
			char* replacestr3 = string_clone( "testing replacelace" );
			char* replacestr4 = string_clone( "" );
			char* replacestr5 = string_clone( "repppppppppp" );

			replacestr = string_replace( replacestr, "rep", "testrep", false );
			replacestr2 = string_replace( replacestr2, "rep", "testrep", true );
			replacestr3 = string_replace( replacestr3, "replace", "testrep", true );
			replacestr4 = string_replace( replacestr4, "foo", "bar", true );
			replacestr5 = string_replace( replacestr5, "rep", "re", true );
		
			EXPECT_TRUE( string_equal( replacestr, "testing testreplace" ) );
			EXPECT_TRUE( string_equal( replacestr2, "testing testreplace" ) );
			EXPECT_TRUE( string_equal( replacestr3, "testing testtestrep" ) );
			EXPECT_TRUE( string_equal( replacestr4, "" ) );
			EXPECT_TRUE( string_equal( replacestr5, "re" ) );

			string_deallocate( replacestr );
			string_deallocate( replacestr2 );
			string_deallocate( replacestr3 );
			string_deallocate( replacestr4 );
			string_deallocate( replacestr5 );
		}
		{
			char* stripstr = string_clone( "   testing strip :   " );
			char* stripstr2 = string_clone( "   testing strip :   " );
			char* stripstr3 = string_clone( "   testing strip :   " );

			stripstr = string_strip( stripstr, " tp:   " );
			stripstr2 = string_strip( stripstr2, "" );
			stripstr3 = string_strip( stripstr3, " tesingrp:" );
		
			EXPECT_TRUE( string_equal( stripstr, "esting stri" ) );
			EXPECT_TRUE( string_equal( stripstr2, "   testing strip :   " ) );
			EXPECT_TRUE( string_equal( stripstr3, "" ) );

			string_deallocate( stripstr );
			string_deallocate( stripstr2 );
			string_deallocate( stripstr3 );
		}
		string_array_deallocate( explodearr );
		string_deallocate( explodestr );
		
		string_deallocate( mergestr );
		string_deallocate( mergestr2 );
		string_deallocate( merged );
		string_array_deallocate( mergearr );
		string_array_deallocate( mergearr2 );
		string_array_deallocate( mergearr3 );

		string_deallocate( splitstr );
		string_deallocate( splitright );
		string_deallocate( splitleft );
		string_deallocate( splitright2 );
		string_deallocate( splitleft2 );

		string_deallocate( substrtest );
	}
	{
		#define SHORTSTRING "short"
		#define LONGSTRING  "long string with dynamic buffer storage but with no real useful data"
		char* clonestr = string_clone( "" );
		char* clonestr2 = string_clone( SHORTSTRING );
		char* clonestr3 = string_clone( LONGSTRING );

		char* teststr = string_clone( clonestr );
		char* teststr2 = string_clone( clonestr2 );
		char* teststr3 = string_clone( clonestr3 );

		char* concatstr = string_concat( clonestr, teststr );
		char* concatstr2 = string_concat( clonestr, teststr2 );
		char* concatstr3 = string_concat( teststr2, clonestr );
		char* concatstr4 = string_concat( clonestr2, teststr2 );
		char* concatstr5 = string_concat( clonestr, teststr3 );
		char* concatstr6 = string_concat( teststr3, clonestr );
		char* concatstr7 = string_concat( clonestr2, teststr3 );
		char* concatstr8 = string_concat( teststr3, clonestr2 );
		char* concatstr9 = string_concat( clonestr3, teststr3 );
		char* concatstr10 = string_concat( teststr3, clonestr3 );
		
		EXPECT_NE( teststr, clonestr );
		EXPECT_TRUE( string_equal( teststr, clonestr ) );
		
		EXPECT_NE( teststr2, clonestr2 );
		EXPECT_TRUE( string_equal( teststr2, clonestr2 ) );

		EXPECT_NE( teststr3, clonestr3 );
		EXPECT_TRUE( string_equal( teststr3, clonestr3 ) );

		EXPECT_TRUE( string_equal( concatstr, "" ) );
		EXPECT_TRUE( string_equal( concatstr2, SHORTSTRING ) );
		EXPECT_TRUE( string_equal( concatstr3, SHORTSTRING ) );
		EXPECT_TRUE( string_equal( concatstr4, SHORTSTRING SHORTSTRING ) );
		EXPECT_TRUE( string_equal( concatstr5, LONGSTRING ) );
		EXPECT_TRUE( string_equal( concatstr6, LONGSTRING ) );
		EXPECT_TRUE( string_equal( concatstr7, SHORTSTRING LONGSTRING ) );
		EXPECT_TRUE( string_equal( concatstr8, LONGSTRING SHORTSTRING ) );
		EXPECT_TRUE( string_equal( concatstr9, LONGSTRING LONGSTRING ) );
		EXPECT_TRUE( string_equal( concatstr10, LONGSTRING LONGSTRING ) );
		
		string_deallocate( teststr );
		string_deallocate( clonestr );
		string_deallocate( teststr2 );
		string_deallocate( clonestr2 );
		string_deallocate( teststr3 );
		string_deallocate( clonestr3 );
		string_deallocate( concatstr );
		string_deallocate( concatstr2 );
		string_deallocate( concatstr3 );
		string_deallocate( concatstr4 );
		string_deallocate( concatstr5 );
		string_deallocate( concatstr6 );
		string_deallocate( concatstr7 );
		string_deallocate( concatstr8 );
		string_deallocate( concatstr9 );
		string_deallocate( concatstr10 );
		#undef SHORTSTRING
		#undef LONGSTRING
	}
	return 0;
}
示例#13
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;
}
示例#14
0
unsigned int stacktrace_capture( void** trace, unsigned int max_depth, unsigned int skip_frames )
{
	unsigned int num_frames = 0;
	
	if( !trace )
		return 0;

	if( !max_depth )
		max_depth = BUILD_SIZE_STACKTRACE_DEPTH;
		
	if( max_depth > BUILD_SIZE_STACKTRACE_DEPTH )
		max_depth = BUILD_SIZE_STACKTRACE_DEPTH;

	if( !_stackwalk_initialized )
	{
		if( !_initialize_stackwalker() )
		{
			memset( trace, 0, sizeof( void* ) * max_depth );
			return num_frames;
		}
	}
		
#if FOUNDATION_PLATFORM_WINDOWS && ( FOUNDATION_COMPILER_MSVC || FOUNDATION_COMPILER_INTEL )
	// Add 1 skip frame for this function call
	++skip_frames;
#  if USE_CAPTURESTACKBACKTRACE
	if( CallRtlCaptureStackBackTrace )
	{
		void* local_trace[BUILD_SIZE_STACKTRACE_DEPTH];
		if( max_depth + skip_frames > BUILD_SIZE_STACKTRACE_DEPTH )
			max_depth = BUILD_SIZE_STACKTRACE_DEPTH - skip_frames;
		num_frames = (unsigned int)CallRtlCaptureStackBackTrace( skip_frames, max_depth, local_trace, 0 );
		if( num_frames > max_depth )
			num_frames = max_depth;
		memcpy( trace, local_trace, sizeof( void* ) * num_frames );
		memset( trace + num_frames, 0, sizeof( void* ) * ( max_depth - num_frames ) );
	}
	else
	{
#  else
	{
#  endif
#  if FOUNDATION_PLATFORM_ARCH_X86_64
	// Raise an exception so helper has access to context record.
	__try
	{
		RaiseException(	0,			// Application-defined exception code.
						0,			// Zero indicates continuable exception.
						0,			// Number of arguments in args array (ignored if args is null)
						0 );		// Array of arguments
	}
	__except( _capture_stack_trace_helper( trace, max_depth, skip_frames, (GetExceptionInformation())->ContextRecord ) )
	{
	}
#  else
	// Use a bit of inline assembly to capture the information relevant to stack walking which is
	// basically EIP and EBP.
	CONTEXT context;
	memset( &context, 0, sizeof( CONTEXT ) );
	context.ContextFlags = CONTEXT_FULL;

	log_warnf( WARNING_DEPRECATED, "********** REIMPLEMENT FALLBACK STACKTRACE **********" );
	/* Use a fake function call to pop the return address and retrieve EIP.*/
	__asm
	{
		call FakeStackTraceCall
		FakeStackTraceCall: 
		pop eax
		mov context.Eip, eax
		mov context.Ebp, ebp
		mov context.Esp, esp
	}

	// Capture the back trace.
	_capture_stack_trace_helper( trace, max_depth, skip_frames, &context );
#  endif
	}
#elif FOUNDATION_PLATFORM_APPLE
	//TODO: Implement
#elif FOUNDATION_PLATFORM_POSIX
	// Add 1 skip frames for this function call
	skip_frames += 1;

	void* localframes[BUILD_SIZE_STACKTRACE_DEPTH];
	num_frames = (unsigned int)backtrace( localframes, BUILD_SIZE_STACKTRACE_DEPTH );

	if( num_frames > skip_frames )
	{
		num_frames -= skip_frames;
		if( num_frames > max_depth )
			num_frames = max_depth;
		memcpy( trace, localframes + skip_frames, sizeof( void* ) * num_frames );
	}
	else
		trace[0] = 0;
#endif

	return num_frames;
}


static bool _symbol_resolve_initialized = false;

static bool _initialize_symbol_resolve()
{
	if( _symbol_resolve_initialized )
		return true;

#if FOUNDATION_PLATFORM_WINDOWS
	{
		unsigned int options;
		void* dll = LoadLibraryA( "PSAPI.DLL" );
		if( !dll )
			return _symbol_resolve_initialized;

		CallEnumProcesses = (EnumProcessesFn)GetProcAddress( dll, "EnumProcesses" );
		CallEnumProcessModules = (EnumProcessModulesFn)GetProcAddress(  dll, "EnumProcessModules" );
		CallGetModuleFileNameEx = (GetModuleFileNameExFn)GetProcAddress(  dll, "GetModuleFileNameExA" );
		CallGetModuleBaseName = (GetModuleBaseNameFn)GetProcAddress(  dll, "GetModuleBaseNameA" );
		CallGetModuleInformation = (GetModuleInformationFn)GetProcAddress( dll, "GetModuleInformation" );

		if( !CallEnumProcesses || !CallEnumProcessModules || !CallGetModuleFileNameEx || !CallGetModuleBaseName || !CallGetModuleInformation )
			return _symbol_resolve_initialized;

		dll = LoadLibraryA( "DBGHELP.DLL" );
		if( !dll )
			return _symbol_resolve_initialized;

		CallSymInitialize = (SymInitializeFn)GetProcAddress( dll, "SymInitialize" );
		CallSymSetOptions = (SymSetOptionsFn)GetProcAddress( dll, "SymSetOptions" );
		CallSymGetOptions = (SymGetOptionsFn)GetProcAddress( dll, "SymGetOptions" );
		CallSymLoadModule64 = (SymLoadModule64Fn)GetProcAddress( dll, "SymLoadModule64" );
		CallSymSetSearchPath = (SymSetSearchPathFn)GetProcAddress( dll, "SymSetSearchPath" );
		CallSymGetModuleInfo64 = (SymGetModuleInfo64Fn)GetProcAddress( dll, "SymGetModuleInfo64" );
		CallSymGetLineFromAddr64 = (SymGetLineFromAddr64Fn)GetProcAddress( dll, "SymGetLineFromAddr64" );
		CallSymGetSymFromAddr64 = (SymGetSymFromAddr64Fn)GetProcAddress( dll, "SymGetSymFromAddr64" );
		CallSymGetModuleBase64 = (SymGetModuleBase64Fn)GetProcAddress( dll, "SymGetModuleBase64" );
		CallSymFunctionTableAccess64 = (SymFunctionTableAccess64Fn)GetProcAddress( dll, "SymFunctionTableAccess64" );

		if( !CallSymInitialize || !CallSymSetOptions || !CallSymGetOptions || !CallSymLoadModule64 || !CallSymSetSearchPath || !CallSymGetModuleInfo64 || !CallSymGetLineFromAddr64 || !CallSymGetSymFromAddr64  || !CallSymGetModuleBase64 || !CallSymFunctionTableAccess64 )
			return _symbol_resolve_initialized;

		options = CallSymGetOptions();
		options |= SYMOPT_LOAD_LINES;
		options |= SYMOPT_DEBUG;
		options |= SYMOPT_UNDNAME;
		options |= SYMOPT_LOAD_LINES;
		options |= SYMOPT_FAIL_CRITICAL_ERRORS;
		options |= SYMOPT_DEFERRED_LOADS;
		options |= SYMOPT_ALLOW_ABSOLUTE_SYMBOLS;
		options |= SYMOPT_EXACT_SYMBOLS;
		options |= SYMOPT_CASE_INSENSITIVE;
		CallSymSetOptions( options );

		CallSymInitialize( GetCurrentProcess(), 0, TRUE );
	}
	
	_load_process_modules();

	_symbol_resolve_initialized = true;

#else
	
	_symbol_resolve_initialized = true;
	
#endif

	return _symbol_resolve_initialized;
}


static NOINLINE char** _resolve_stack_frames( void** frames, unsigned int max_frames )
{
#if FOUNDATION_PLATFORM_WINDOWS
	char**              lines = 0;
	char                symbol_buffer[ sizeof( IMAGEHLP_SYMBOL64 ) + 512 ];
	PIMAGEHLP_SYMBOL64  symbol;
	DWORD               displacement = 0;
	uint64_t            displacement64 = 0;
	unsigned int        iaddr = 0;
	unsigned int        last_error;
	bool                found = false;
	HANDLE              process_handle = GetCurrentProcess();
	int                 buffer_offset = 0;
	bool                last_was_main = false;
	IMAGEHLP_LINE64     line64;
	IMAGEHLP_MODULE64   module64;

	for( iaddr = 0; ( iaddr < max_frames ) && !last_was_main; ++iaddr )
	{
		char* resolved = 0;
		const char* function_name = "??";
		const char* file_name = "??";
		const char* module_name = "??";
		unsigned int line_number = 0;

		//Allow first frame to be null in case of a function call to a null pointer
		if( iaddr && !frames[iaddr] )
			break;

		// Initialize symbol.
		symbol = (PIMAGEHLP_SYMBOL64)symbol_buffer;
		memset( symbol, 0, sizeof( symbol_buffer ) );
		symbol->SizeOfStruct = sizeof( symbol_buffer );
		symbol->MaxNameLength = 512;

		// Get symbol from address.
		if( CallSymGetSymFromAddr64 && CallSymGetSymFromAddr64( process_handle, (uint64_t)((uintptr_t)frames[iaddr]), &displacement64, symbol ) )
		{
			int offset = 0;
			while( symbol->Name[offset] < 32 )
				++offset;
			function_name = symbol->Name + offset;
		}
		else
		{
			// No symbol found for this address.
			last_error = GetLastError();
		}

		memset( &line64, 0, sizeof( line64 ) );
		line64.SizeOfStruct = sizeof( line64 );
		if( CallSymGetLineFromAddr64 && CallSymGetLineFromAddr64( process_handle, (uint64_t)((uintptr_t)frames[iaddr]), &displacement, &line64 ) )
		{
			file_name = line64.FileName;
			line_number = line64.LineNumber;
		}

		memset( &module64, 0, sizeof( module64 ) );
		module64.SizeOfStruct = sizeof( module64 );
		if( CallSymGetModuleInfo64 && CallSymGetModuleInfo64( process_handle, (uint64_t)((uintptr_t)frames[iaddr]), &module64 ) )
		{
			int last_slash = STRING_NPOS;
			module_name = module64.ImageName;
			last_slash = string_rfind( module_name, '\\', STRING_NPOS );
			if( last_slash != STRING_NPOS )
				module_name += last_slash + 1;
		}

		resolved = string_format( "[" STRING_FORMAT_POINTER "] %s (%s:%d +%d bytes) [in %s]", frames[iaddr], function_name, file_name, line_number, displacement, module_name );
		array_push( lines, resolved );
	
		if( string_equal( function_name, "main" ) )
			last_was_main = true;
	}

	return lines;

#elif FOUNDATION_PLATFORM_LINUX

	char** addrs = 0;
	char** lines = 0;
	const char** args = 0;
	process_t* proc = process_allocate();
	unsigned int num_frames = 0;
	unsigned int requested_frames = 0;
	bool last_was_main = false;

	if( !string_length( environment_executable_path() ) )
	{
		for( unsigned int iaddr = 0; iaddr < max_frames; ++iaddr )
		{
			//Allow first frame to be null in case of a function call to a null pointer
			if( iaddr && !frames[iaddr] )
				break;
		
			array_push( lines, string_format( "[" STRING_FORMAT_POINTER "]", frames[iaddr] ) );
		}
		return lines;
	}
	
	array_push( args, "-e" );
	array_push( args, environment_executable_path() );
	array_push( args, "-f" );

	for( unsigned int iaddr = 0; iaddr < max_frames; ++iaddr )
	{
		//Allow first frame to be null in case of a function call to a null pointer
		if( iaddr && !frames[iaddr] )
			break;
		
		char* addr = string_format( STRING_FORMAT_POINTER, frames[iaddr] );
		array_push( addrs, addr );
		array_push( args, addr );

		++requested_frames;
	}
	
	process_set_working_directory( proc, environment_initial_working_directory() );
	process_set_executable_path( proc, "/usr/bin/addr2line" );
	process_set_arguments( proc, args, array_size( args ) );
	process_set_flags( proc, PROCESS_ATTACHED | PROCESS_STDSTREAMS );

	process_spawn( proc );

	stream_t* procout = process_stdout( proc );
	while( !stream_eos( procout ) && ( num_frames < requested_frames ) && !last_was_main )
	{
		char* function = stream_read_line( procout, '\n' );
		char* filename = stream_read_line( procout, '\n' );

		array_push( lines, string_format( "[" STRING_FORMAT_POINTER "] %s (%s)",
			frames[num_frames],
			function && string_length( function ) ? function : "??",
			filename && string_length( filename ) ? filename : "??"
		) );
	
		if( string_equal( function, "main" ) )
			last_was_main = true;

		string_deallocate( function );
		string_deallocate( filename );

		++num_frames;
	}
	
	process_wait( proc );
	process_deallocate( proc );
	
	string_array_deallocate( addrs );
	array_deallocate( args );	
	
	return lines;
	
#else

	char** lines = 0;
	for( unsigned int iaddr = 0; iaddr < max_frames; ++iaddr )
	{
		//Allow first frame to be null in case of a function call to a null pointer
		if( iaddr && !frames[iaddr] )
			break;
		
		array_push( lines, string_format( "[" STRING_FORMAT_POINTER "]\n", frames[iaddr] ) );
	}
		
	return lines;

#endif
}
示例#15
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;
}
示例#16
0
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;
}