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(md5, reference) { md5_t* md5; char md5str[32]; string_t digest; md5 = md5_allocate(); md5_digest_finalize(md5); md5_digest(md5, "testing md5 implementation", 26); md5_digest_finalize(md5); digest = md5_get_digest(md5, md5str, sizeof(md5str)); EXPECT_STRINGEQ(digest, string_const(STRING_CONST("4E24E37E5E06F23210FA1518E97A50C4"))); md5_digest(md5, "testing md5 implementation", 26); md5_digest(md5, "", 0); md5_digest(md5, "further testing md5 implementation with long buffer > 32 bytes", 62); md5_digest_finalize(md5); digest = md5_get_digest(md5, md5str, sizeof(md5str)); EXPECT_STRINGEQ(digest, string_const(STRING_CONST("BD870884942EA7B32A9CB2547B02B871"))); md5_digest(md5, digest_test_string, 2000); md5_digest_finalize(md5); digest = md5_get_digest(md5, md5str, sizeof(md5str)); EXPECT_STRINGEQ(digest, string_const(STRING_CONST("137D3C94230A0E230C4DDFC97EACCCD2"))); md5_deallocate(md5); return 0; }
static application_t test_matrix_application(void) { application_t app = {0}; app.name = string_const(STRING_CONST("Matrix tests")); app.short_name = string_const(STRING_CONST("test_matrix")); app.company = string_const(STRING_CONST("Rampant Pixels")); app.version = vector_module_version(); app.flags = APPLICATION_UTILITY; app.exception_handler = test_exception_handler; return app; }
static application_t test_error_application(void) { application_t app; memset(&app, 0, sizeof(app)); app.name = string_const(STRING_CONST("Foundation error tests")); app.short_name = string_const(STRING_CONST("test_error")); app.company = string_const(STRING_CONST("Rampant Pixels")); app.flags = APPLICATION_UTILITY; app.exception_handler = test_exception_handler; return app; }
static application_t test_environment_application(void) { application_t app; memset(&app, 0, sizeof(app)); app.name = string_const(STRING_CONST("Foundation environment tests")); app.short_name = string_const(STRING_CONST("test_environment")); app.config_dir = string_const(STRING_CONST("test_environment")); app.flags = APPLICATION_UTILITY; app.dump_callback = test_crash_handler; return app; }
int main_initialize(void) { foundation_config_t config; application_t application; int ret; size_t iarg, asize; const string_const_t* cmdline = environment_command_line(); _test_memory_tracker = true; for (iarg = 0, asize = array_size(cmdline); iarg < asize; ++iarg) { if (string_equal(STRING_ARGS(cmdline[iarg]), STRING_CONST("--no-memory-tracker"))) _test_memory_tracker = false; } if (_test_memory_tracker) memory_set_tracker(memory_tracker_local()); memset(&config, 0, sizeof(config)); memset(&application, 0, sizeof(application)); application.name = string_const(STRING_CONST("Task library test suite")); application.short_name = string_const(STRING_CONST("test_all")); application.company = string_const(STRING_CONST("Rampant Pixels")); application.version = task_module_version(); application.flags = APPLICATION_UTILITY; application.exception_handler = test_exception_handler; log_set_suppress(0, ERRORLEVEL_INFO); #if ( FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID ) && BUILD_ENABLE_LOG log_set_handler(test_log_handler); #endif #if !FOUNDATION_PLATFORM_IOS && !FOUNDATION_PLATFORM_ANDROID && !FOUNDATION_PLATFORM_PNACL _test_should_start = true; #endif ret = foundation_initialize(memory_system_malloc(), application, config); #if BUILD_MONOLITHIC if (ret == 0) { task_config_t task_config; memset(&task_config, 0, sizeof(task_config)); ret = task_module_initialize(task_config); test_set_suitable_working_directory(); } #endif return ret; }
DECLARE_TEST(error, context) { error_context_t* context = 0; context = error_context(); if (context) EXPECT_EQ(context->depth, 0); error_context_push(STRING_CONST("error test"), STRING_CONST("data")); context = error_context(); #if BUILD_ENABLE_ERROR_CONTEXT EXPECT_NE(context, 0); EXPECT_EQ(context->depth, 1); EXPECT_CONSTSTRINGEQ(context->frame[0].name, string_const(STRING_CONST("error test"))); EXPECT_CONSTSTRINGEQ(context->frame[0].data, string_const(STRING_CONST("data"))); #else EXPECT_EQ(context, 0); #endif error_context_pop(); context = error_context(); #if BUILD_ENABLE_ERROR_CONTEXT EXPECT_NE(context, 0); EXPECT_EQ(context->depth, 0); #else EXPECT_EQ(context, 0); #endif error_context_push(STRING_CONST("error test"), STRING_CONST("data")); error_context_push(STRING_CONST("another test"), STRING_CONST("more data")); context = error_context(); #if BUILD_ENABLE_ERROR_CONTEXT EXPECT_NE(context, 0); EXPECT_EQ(context->depth, 2); EXPECT_CONSTSTRINGEQ(context->frame[0].name, string_const(STRING_CONST("error test"))); EXPECT_CONSTSTRINGEQ(context->frame[0].data, string_const(STRING_CONST("data"))); EXPECT_CONSTSTRINGEQ(context->frame[1].name, string_const(STRING_CONST("another test"))); EXPECT_CONSTSTRINGEQ(context->frame[1].data, string_const(STRING_CONST("more data"))); #else EXPECT_EQ(context, 0); #endif error_context_pop(); context = error_context(); #if BUILD_ENABLE_ERROR_CONTEXT EXPECT_NE(context, 0); EXPECT_EQ(context->depth, 1); EXPECT_CONSTSTRINGEQ(context->frame[0].name, string_const(STRING_CONST("error test"))); EXPECT_CONSTSTRINGEQ(context->frame[0].data, string_const(STRING_CONST("data"))); #else EXPECT_EQ(context, 0); #endif error_context_pop(); return 0; }
DECLARE_TEST(foundation, log) { lua_t* env = lua_allocate(); log_set_suppress(HASH_LUA, ERRORLEVEL_NONE); EXPECT_NE(env, 0); string_const_t testcode = string_const(STRING_CONST( "local ffi = require(\"ffi\")\n" "local foundation = require(\"foundation\")\n" "local C = ffi.C\n" "C.log_set_suppress(foundation.HASH_LUA, foundation.ERRORLEVEL_NONE)\n" "foundation.log.debug(\"Testing log debug output\")\n" "foundation.log.info(\"Testing log info output\")\n" "foundation.log.warn(\"Testing log warning output\")\n" "C.log_enable_prefix(false)\n" "foundation.log.error(\"Testing log error output without prefix\")\n" "C.log_enable_stdout(false)\n" "foundation.log.debug(\"Invisible on stdout\")\n" "C.log_enable_stdout(true)\n" "C.log_enable_prefix(true)\n" "C.log_set_suppress(foundation.HASH_LUA, foundation.ERRORLEVEL_INFO)\n" )); EXPECT_EQ(lua_eval_string(env, STRING_ARGS(testcode)), LUA_OK); EXPECT_EQ(error(), ERROR_SCRIPT); lua_deallocate(env); return 0; }
DECLARE_TEST(foundation, environment) { lua_t* env = lua_allocate(); log_set_suppress(HASH_LUA, ERRORLEVEL_NONE); log_info(HASH_LUA, STRING_CONST("Running environment lua tests")); EXPECT_NE(env, 0); string_const_t testcode = string_const(STRING_CONST( "local ffi = require(\"ffi\")\n" "local foundation = require(\"foundation\")\n" "local C = ffi.C\n" "C.log_set_suppress(foundation.HASH_LUA, foundation.ERRORLEVEL_DEBUG)\n" "C.log_enable_prefix(false)\n" "foundation.log.info(\"Executable name: \" .. tostring(C.environment_executable_name()))\n" "local cmdline = \"\"\n" "local cmdline_tab = C.environment_command_line()\n" "local num = C.array_size(cmdline_tab)" "for i = 0, num-1 do\n" " cmdline = cmdline .. \" \" .. tostring(cmdline_tab[i])\n" "end\n" "foundation.log.info(\"Command line:\" .. cmdline)\n" "C.log_enable_prefix(true)\n" "C.log_set_suppress(foundation.HASH_LUA, foundation.ERRORLEVEL_INFO)\n" )); EXPECT_EQ(lua_eval_string(env, STRING_ARGS(testcode)), LUA_OK); log_info(HASH_LUA, STRING_CONST("Done running environment lua tests")); log_set_suppress(HASH_LUA, ERRORLEVEL_INFO); lua_deallocate(env); return 0; }
DECLARE_TEST(environment, workingdir) { char buffer[BUILD_MAX_PATHLEN]; string_const_t working_dir = environment_current_working_directory(); string_const_t new_working_dir = path_directory_name(STRING_ARGS(working_dir)); string_t working_dir_copy = string_clone(STRING_ARGS(working_dir)); string_t new_working_dir_copy; if (string_equal(STRING_ARGS(working_dir), STRING_CONST("/"))) { string_t tmpwork = path_make_temporary(buffer, sizeof(buffer)); new_working_dir = path_directory_name(STRING_ARGS(tmpwork)); } new_working_dir_copy = string_clone(STRING_ARGS(new_working_dir)); new_working_dir = string_to_const(new_working_dir_copy); EXPECT_CONSTSTRINGNE(working_dir, new_working_dir); #if FOUNDATION_PLATFORM_PNACL EXPECT_FALSE(environment_set_current_working_directory(STRING_ARGS(new_working_dir))); EXPECT_CONSTSTRINGEQ(environment_current_working_directory(), string_const(STRING_ARGS(working_dir_copy))); #else EXPECT_TRUE(environment_set_current_working_directory(STRING_ARGS(new_working_dir))); EXPECT_CONSTSTRINGEQ(environment_current_working_directory(), new_working_dir); environment_set_current_working_directory(STRING_ARGS(working_dir_copy)); EXPECT_CONSTSTRINGEQ(environment_current_working_directory(), string_const(STRING_ARGS(working_dir_copy))); { log_enable_stdout(false); bool ret = environment_set_current_working_directory(STRING_CONST("/invalid/path/which/does/not/exist")); log_enable_stdout(true); EXPECT_FALSE(ret); } EXPECT_CONSTSTRINGEQ(environment_current_working_directory(), string_const(STRING_ARGS(working_dir_copy))); #endif string_deallocate(new_working_dir_copy.str); string_deallocate(working_dir_copy.str); return 0; }
int main_initialize(void) { int ret = 0; application_t application; foundation_config_t foundation_config; resource_config_t resource_config; window_config_t window_config; render_config_t render_config; memset(&foundation_config, 0, sizeof(foundation_config)); memset(&resource_config, 0, sizeof(resource_config)); memset(&window_config, 0, sizeof(window_config)); memset(&render_config, 0, sizeof(render_config)); memset(&application, 0, sizeof(application)); application.name = string_const(STRING_CONST("rendercompile")); application.short_name = string_const(STRING_CONST("rendercompile")); application.config_dir = string_const(STRING_CONST("rendercompile")); application.flags = APPLICATION_UTILITY; log_enable_prefix(false); log_set_suppress(0, ERRORLEVEL_WARNING); resource_config.enable_local_source = true; resource_config.enable_local_cache = true; resource_config.enable_remote_cache = true; if ((ret = foundation_initialize(memory_system_malloc(), application, foundation_config)) < 0) return ret; if ((ret = resource_module_initialize(resource_config)) < 0) return ret; if ((ret = window_module_initialize(window_config)) < 0) return ret; if ((ret = render_module_initialize(render_config)) < 0) return ret; log_set_suppress(HASH_RESOURCE, ERRORLEVEL_DEBUG); log_set_suppress(HASH_RENDER, ERRORLEVEL_INFO); return 0; }
DECLARE_TEST(md5, empty) { md5_t* md5; char md5str[32]; string_t digest; md5 = md5_allocate(); md5_digest_finalize(md5); digest = md5_get_digest(md5, md5str, sizeof(md5str)); EXPECT_STRINGEQ(digest, string_const(STRING_CONST("D41D8CD98F00B204E9800998ECF8427E"))); md5_initialize(md5); md5_digest_finalize(md5); digest = md5_get_digest(md5, md5str, sizeof(md5str)); EXPECT_STRINGEQ(digest, string_const(STRING_CONST("D41D8CD98F00B204E9800998ECF8427E"))); md5_deallocate(md5); return 0; }
int main_initialize(void) { int ret = 0; application_t application; foundation_config_t config; memset(&config, 0, sizeof(config)); memset(&application, 0, sizeof(application)); application.name = string_const(STRING_CONST("hashify")); application.short_name = string_const(STRING_CONST("hashify")); application.flags = APPLICATION_UTILITY; log_enable_prefix(false); log_set_suppress(0, ERRORLEVEL_ERROR); if ((ret = foundation_initialize(memory_system_malloc(), application, config)) < 0) return ret; return 0; }
int main_initialize(void) { int ret = 0; application_t application; memset(&application, 0, sizeof(application)); application.name = string_const(STRING_CONST("Vector mask generator")); application.short_name = string_const(STRING_CONST("maskgen")); application.company = string_const(STRING_CONST("Rampant Pixels")); application.version = vector_module_version(); application.flags = APPLICATION_UTILITY; log_enable_prefix(false); foundation_config_t config; memset(&config, 0, sizeof(config)); if ((ret = foundation_initialize(memory_system_malloc(), application, config)) < 0) return ret; return 0; }
DECLARE_TEST(mutex, basic) { mutex_t* mutex; mutex = mutex_allocate(STRING_CONST("test")); EXPECT_CONSTSTRINGEQ(mutex_name(mutex), string_const(STRING_CONST("test"))); EXPECT_TRUE(mutex_try_lock(mutex)); EXPECT_TRUE(mutex_lock(mutex)); EXPECT_TRUE(mutex_try_lock(mutex)); EXPECT_TRUE(mutex_lock(mutex)); EXPECT_TRUE(mutex_unlock(mutex)); EXPECT_TRUE(mutex_unlock(mutex)); EXPECT_TRUE(mutex_unlock(mutex)); EXPECT_TRUE(mutex_unlock(mutex)); log_set_suppress(0, ERRORLEVEL_WARNING); EXPECT_FALSE(mutex_unlock(mutex)); log_set_suppress(0, ERRORLEVEL_INFO); mutex_signal(mutex); thread_yield(); EXPECT_TRUE(mutex_try_wait(mutex, 1)); EXPECT_TRUE(mutex_unlock(mutex)); mutex_signal(mutex); thread_yield(); EXPECT_TRUE(mutex_wait(mutex)); EXPECT_TRUE(mutex_unlock(mutex)); log_set_suppress(0, ERRORLEVEL_WARNING); EXPECT_FALSE(mutex_try_wait(mutex, 100)); EXPECT_FALSE(mutex_unlock(mutex)); log_set_suppress(0, ERRORLEVEL_INFO); mutex_signal(mutex); thread_yield(); EXPECT_TRUE(mutex_try_wait(mutex, 1)); log_set_suppress(0, ERRORLEVEL_WARNING); EXPECT_FALSE(mutex_try_wait(mutex, 100)); EXPECT_TRUE(mutex_unlock(mutex)); EXPECT_FALSE(mutex_unlock(mutex)); log_set_suppress(0, ERRORLEVEL_INFO); mutex_deallocate(mutex); return 0; }
static int lua_import_output(const uuid_t uuid, const luaimport_dump_t* dump) { resource_source_t source; hash_t checksum; tick_t timestamp; uint64_t platform; string_const_t type = string_const(STRING_CONST("lua")); int ret = 0; resource_source_initialize(&source); resource_source_read(&source, uuid); timestamp = time_system(); platform = 0; checksum = hash(dump->bytecode, dump->bytecode_size); if (resource_source_write_blob(uuid, timestamp, HASH_SOURCE, platform, checksum, dump->bytecode, dump->bytecode_size)) { resource_source_set_blob(&source, timestamp, HASH_SOURCE, platform, checksum, dump->bytecode_size); } else { ret = -1; goto finalize; } resource_source_set(&source, timestamp, HASH_RESOURCE_TYPE, 0, STRING_ARGS(type)); if (!resource_source_write(&source, uuid, false)) { ret = -1; goto finalize; } finalize: resource_source_finalize(&source); return ret; }
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_initialize(void) { foundation_config_t config; application_t application; int ret; size_t iarg, asize; const string_const_t* cmdline = environment_command_line(); _test_memory_tracker = true; for (iarg = 0, asize = array_size(cmdline); iarg < asize; ++iarg) { if (string_equal(STRING_ARGS(cmdline[iarg]), STRING_CONST("--no-memory-tracker"))) _test_memory_tracker = false; } if (_test_memory_tracker) memory_set_tracker(memory_tracker_local()); memset(&config, 0, sizeof(config)); #if BUILD_MONOLITHIC //For fs monitor test config.fs_monitor_max = 1; //For temporary allocator test, 256KiB config.temporary_memory = 256 * 1024; //For testing static hash store config.hash_store_size = 32 * 1024; //Test preallocation of random state buffers config.random_state_prealloc = 4; #endif memset(&application, 0, sizeof(application)); application.name = string_const(STRING_CONST("Foundation library test suite")); application.short_name = string_const(STRING_CONST("test_all")); application.company = string_const(STRING_CONST("Rampant Pixels")); application.version = foundation_version(); application.flags = APPLICATION_UTILITY; application.exception_handler = test_exception_handler; log_set_suppress(0, ERRORLEVEL_INFO); #if (FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID) && BUILD_ENABLE_LOG log_set_handler(test_log_handler); #endif #if !FOUNDATION_PLATFORM_IOS && !FOUNDATION_PLATFORM_ANDROID && !FOUNDATION_PLATFORM_PNACL _test_should_start = true; #endif ret = foundation_initialize(memory_system_malloc(), application, config); #if BUILD_MONOLITHIC //For monolithic process test if (string_array_find(cmdline, array_size(cmdline), STRING_CONST("wait for kill")) >= 0) { while (true) thread_sleep(100); } test_set_suitable_working_directory(); #endif return ret; }
DECLARE_TEST(exception, assert_handler) { EXPECT_EQ(assert_handler(), 0); assert_set_handler(handle_assert); EXPECT_EQ(assert_handler(), handle_assert); log_enable_stdout(false); EXPECT_EQ(assert_report(1, STRING_CONST("condition"), STRING_CONST("file"), 2, STRING_CONST("msg")), 1234); log_enable_stdout(true); EXPECT_EQ(assert_handler(), handle_assert); EXPECT_EQ(handled_context, 1); EXPECT_STRINGEQ(string(handled_condition, string_length(handled_condition)), string_const(STRING_CONST("condition"))); EXPECT_STRINGEQ(string(handled_file, string_length(handled_file)), string_const(STRING_CONST("file"))); EXPECT_EQ(handled_line, 2); EXPECT_STRINGEQ(string(handled_msg, string_length(handled_msg)), string_const(STRING_CONST("msg"))); assert_set_handler(0); EXPECT_EQ(assert_handler(), 0); #if BUILD_ENABLE_LOG _global_log_handler = log_handler(); log_set_handler(handle_log); #endif log_enable_stdout(false); EXPECT_EQ(assert_report_formatted(1, STRING_CONST("assert_report_formatted"), STRING_CONST("file"), 2, STRING_CONST("%.*s"), 3, "msg"), 1); log_enable_stdout(true); EXPECT_EQ(error(), ERROR_ASSERT); #if BUILD_ENABLE_LOG EXPECT_TRUE(string_find_string(handled_log, string_length(handled_log), STRING_CONST("assert_report_formatted"), 0) != STRING_NPOS); EXPECT_TRUE(string_find_string(handled_log, string_length(handled_log), STRING_CONST("msg"), 0) != STRING_NPOS); log_enable_stdout(false); log_set_suppress(HASH_TEST, ERRORLEVEL_NONE); #if BUILD_ENABLE_DEBUG_LOG log_debugf(HASH_TEST, STRING_CONST("%s"), #else log_infof(HASH_TEST, STRING_CONST("%s"), #endif "To test log handler and memory handling this test will print " "a really long log line with complete nonsense. Log handlers only occur for non-suppressed " "log levels, which is why this will be visible. However, it will not be printed to stdout. " "Lorem ipsum dolor sit amet, an quas vivendum sed, in est summo conclusionemque, an est nulla nonumy option. " "Malorum invidunt et mel, mei et hinc adolescens, eu velit deleniti urbanitas cum. Ei pericula omittantur duo, " "eam ei malis pertinacia, eum hinc dictas et. Duo et velit dolorem explicari, an tacimates abhorreant qui, " "esse possit intellegat ad vis. Eros populo numquam pro ea. Eius altera volumus duo ex, offendit comprehensam " "sit te. Ea facete nostrum fabellas sea. Vel ea rebum ridens quodsi, etiam urbanitas mea an. Ornatus commune et his, " "quo habeo denique an, id his amet diceret. Eam ei essent denique, cu quaestio perpetua vim. Mei utamur maluisset ex, " "iriure tritani eu per. Pro at rebum maluisset, nec ei eirmod scaevola consulatu, ius in meis patrioque. Vis at summo " "ancillae omnesque, inani moderatius delicatissimi qui an. Et illum vocibus eum, aliquando intellegat ex ius. Ius at " "tation veritus. Scripta reprehendunt at sed. Hinc idque mollis in cum, at elit habemus civibus eam, sea et modus " "eripuit. Alii ipsum electram id vel, mei alterum percipitur cu. Pro cu minim erant graecis, no vis tation nominavi " "imperdiet, mei affert probatus ut. Quo veri modus ad, solet nostrud atomorum ius ea. Everti aliquid ne usu, populo " "sapientem pro te. Persecuti definitionem qui ei, dicit dicunt ea quo. Sed minimum copiosae ei, pri dicat possit " "urbanitas eu. Tritani interesset theophrastus id sit, phaedrum facilisis his eu. Dictas accusam eu quo. Ea democritum " "consetetur vel. Iudicabit definitionem est eu, oportere temporibus at nec." ); log_set_suppress(HASH_TEST, ERRORLEVEL_DEBUG); log_enable_stdout(true); EXPECT_TRUE(string_find_string(handled_log, string_length(handled_log), STRING_CONST("Lorem ipsum"), 0) != STRING_NPOS); log_set_handler(_global_log_handler); #endif return 0; }
DECLARE_TEST(error, output) { #if BUILD_ENABLE_LOG error_handler_fn handler_error = error_handler(); log_handler_fn handler_log = log_handler(); string_const_t shortmsg = string_const(STRING_CONST("Short message with prefix")); string_const_t longmsg = string_const(STRING_CONST("Longer message which should be output without a prefix")); error_set_handler(ignore_error_handler); log_set_handler(log_verify_handler); log_enable_stdout(false); EXPECT_EQ(log_stdout(), false); log_warn(HASH_TEST, WARNING_SUSPICIOUS, STRING_ARGS(shortmsg)); log_enable_stdout(true); EXPECT_EQ(log_stdout(), true); EXPECT_EQ(_last_log_context, HASH_TEST); EXPECT_EQ(_last_log_severity, ERRORLEVEL_WARNING); EXPECT_GE(_last_log_length, shortmsg.length); EXPECT_NE(string_find_string(_last_log_msg, _last_log_length, STRING_ARGS(shortmsg), 0), STRING_NPOS); EXPECT_GT(string_find_string(_last_log_msg, _last_log_length, STRING_ARGS(shortmsg), 0), 0); EXPECT_NE(string_find_string(_last_log_msg, _last_log_length, STRING_CONST("WARNING [suspicious]"), 0), STRING_NPOS); _last_log_context = 0; _last_log_severity = ERRORLEVEL_NONE; _last_log_msg = nullptr; _last_log_length = 0; log_enable_stdout(false); log_warn(HASH_TEST, (warning_t)0x1000, STRING_ARGS(shortmsg)); log_enable_stdout(true); EXPECT_EQ(_last_log_context, HASH_TEST); EXPECT_EQ(_last_log_severity, ERRORLEVEL_WARNING); EXPECT_GE(_last_log_length, shortmsg.length); EXPECT_NE(string_find_string(_last_log_msg, _last_log_length, STRING_ARGS(shortmsg), 0), STRING_NPOS); EXPECT_GT(string_find_string(_last_log_msg, _last_log_length, STRING_ARGS(shortmsg), 0), 0); EXPECT_NE(string_find_string(_last_log_msg, _last_log_length, STRING_CONST("WARNING [4096]"), 0), STRING_NPOS); _last_log_context = 0; _last_log_severity = ERRORLEVEL_NONE; _last_log_msg = nullptr; _last_log_length = 0; log_enable_prefix(false); log_enable_stdout(false); log_warn(HASH_TEST, WARNING_SYSTEM_CALL_FAIL, STRING_ARGS(longmsg)); log_enable_stdout(true); log_enable_prefix(true); EXPECT_EQ(_last_log_context, HASH_TEST); EXPECT_EQ(_last_log_severity, ERRORLEVEL_WARNING); EXPECT_NE(string_find_string(_last_log_msg, _last_log_length, STRING_ARGS(longmsg), 0), STRING_NPOS); EXPECT_GT(string_find_string(_last_log_msg, _last_log_length, STRING_ARGS(longmsg), 0), 0); _last_log_context = 0; _last_log_severity = ERRORLEVEL_NONE; _last_log_msg = nullptr; _last_log_length = 0; log_enable_stdout(false); log_error(HASH_TEST, ERROR_DEPRECATED, STRING_ARGS(shortmsg)); log_enable_stdout(true); EXPECT_EQ(_last_log_context, HASH_TEST); EXPECT_EQ(_last_log_severity, ERRORLEVEL_ERROR); EXPECT_GE(_last_log_length, shortmsg.length); EXPECT_NE(string_find_string(_last_log_msg, _last_log_length, STRING_ARGS(shortmsg), 0), STRING_NPOS); EXPECT_GT(string_find_string(_last_log_msg, _last_log_length, STRING_ARGS(shortmsg), 0), 0); EXPECT_NE(string_find_string(_last_log_msg, _last_log_length, STRING_CONST("ERROR [deprecated]"), 0), STRING_NPOS); _last_log_context = 0; _last_log_severity = ERRORLEVEL_NONE; _last_log_msg = nullptr; _last_log_length = 0; log_enable_stdout(false); log_error(HASH_TEST, (error_t)0x1000, STRING_ARGS(shortmsg)); log_enable_stdout(true); EXPECT_EQ(_last_log_context, HASH_TEST); EXPECT_EQ(_last_log_severity, ERRORLEVEL_ERROR); EXPECT_GE(_last_log_length, shortmsg.length); EXPECT_NE(string_find_string(_last_log_msg, _last_log_length, STRING_ARGS(shortmsg), 0), STRING_NPOS); EXPECT_GT(string_find_string(_last_log_msg, _last_log_length, STRING_ARGS(shortmsg), 0), 0); EXPECT_NE(string_find_string(_last_log_msg, _last_log_length, STRING_CONST("ERROR [4096]"), 0), STRING_NPOS); _last_log_context = 0; _last_log_severity = ERRORLEVEL_NONE; _last_log_msg = nullptr; _last_log_length = 0; log_enable_prefix(false); log_enable_stdout(false); log_error(HASH_TEST, ERROR_INVALID_VALUE, STRING_ARGS(longmsg)); log_enable_stdout(true); log_enable_prefix(true); EXPECT_EQ(_last_log_context, HASH_TEST); EXPECT_EQ(_last_log_severity, ERRORLEVEL_ERROR); EXPECT_NE(string_find_string(_last_log_msg, _last_log_length, STRING_ARGS(longmsg), 0), STRING_NPOS); EXPECT_GT(string_find_string(_last_log_msg, _last_log_length, STRING_ARGS(longmsg), 0), 0); _last_log_context = 0; _last_log_severity = ERRORLEVEL_NONE; _last_log_msg = nullptr; _last_log_length = 0; log_enable_stdout(false); log_panic(HASH_TEST, ERROR_DEPRECATED, STRING_ARGS(shortmsg)); log_enable_stdout(true); EXPECT_EQ(_last_log_context, HASH_TEST); EXPECT_EQ(_last_log_severity, ERRORLEVEL_PANIC); EXPECT_GE(_last_log_length, shortmsg.length); EXPECT_NE(string_find_string(_last_log_msg, _last_log_length, STRING_ARGS(shortmsg), 0), STRING_NPOS); EXPECT_GT(string_find_string(_last_log_msg, _last_log_length, STRING_ARGS(shortmsg), 0), 0); EXPECT_NE(string_find_string(_last_log_msg, _last_log_length, STRING_CONST("PANIC [deprecated]"), 0), STRING_NPOS); _last_log_context = 0; _last_log_severity = ERRORLEVEL_NONE; _last_log_msg = nullptr; _last_log_length = 0; log_enable_stdout(false); log_panic(HASH_TEST, (error_t)0x1000, STRING_ARGS(shortmsg)); log_enable_stdout(true); EXPECT_EQ(_last_log_context, HASH_TEST); EXPECT_EQ(_last_log_severity, ERRORLEVEL_PANIC); EXPECT_GE(_last_log_length, shortmsg.length); EXPECT_NE(string_find_string(_last_log_msg, _last_log_length, STRING_ARGS(shortmsg), 0), STRING_NPOS); EXPECT_GT(string_find_string(_last_log_msg, _last_log_length, STRING_ARGS(shortmsg), 0), 0); EXPECT_NE(string_find_string(_last_log_msg, _last_log_length, STRING_CONST("PANIC [4096]"), 0), STRING_NPOS); _last_log_context = 0; _last_log_severity = ERRORLEVEL_NONE; _last_log_msg = nullptr; _last_log_length = 0; log_enable_prefix(false); log_enable_stdout(false); log_panic(HASH_TEST, ERROR_INVALID_VALUE, STRING_ARGS(longmsg)); log_enable_stdout(true); log_enable_prefix(true); EXPECT_EQ(_last_log_context, HASH_TEST); EXPECT_EQ(_last_log_severity, ERRORLEVEL_PANIC); EXPECT_NE(string_find_string(_last_log_msg, _last_log_length, STRING_ARGS(longmsg), 0), STRING_NPOS); EXPECT_GT(string_find_string(_last_log_msg, _last_log_length, STRING_ARGS(longmsg), 0), 0); # if BUILD_ENABLE_ERROR_CONTEXT error_context_push(STRING_CONST("one"), STRING_CONST("dataone")); error_context_push(STRING_CONST("two"), STRING_CONST("datatwo")); error_context_push(STRING_CONST("three"), STRING_CONST("datathree")); _last_log_context = 0; _last_log_severity = ERRORLEVEL_NONE; _last_log_msg = nullptr; _last_log_length = 0; log_enable_stdout(false); log_error_context(HASH_TEST, ERRORLEVEL_INFO); log_enable_stdout(true); error_context_pop(); error_context_pop(); error_context_pop(); EXPECT_SIZEEQ(string_find_string(_last_log_msg, _last_log_length, STRING_CONST("When one: dataone"), 0), STRING_NPOS); EXPECT_SIZEEQ(string_find_string(_last_log_msg, _last_log_length, STRING_CONST("When two: datatwo"), 0), STRING_NPOS); EXPECT_SIZENE(string_find_string(_last_log_msg, _last_log_length, STRING_CONST("When three: datathree"), 0), STRING_NPOS); # endif log_set_handler(handler_log); error_set_handler(handler_error); #endif return 0; }
DECLARE_TEST(exception, error) { error_handler_fn handler; int ret; error(); EXPECT_EQ(error(), ERROR_NONE); error_report(ERRORLEVEL_ERROR, ERROR_NONE); EXPECT_EQ(error(), ERROR_NONE); error_report(ERRORLEVEL_ERROR, ERROR_EXCEPTION); EXPECT_EQ(error(), ERROR_EXCEPTION); handler = error_handler(); error_set_handler(_error_handler_test); ret = error_report(ERRORLEVEL_WARNING, ERROR_INVALID_VALUE); EXPECT_EQ(error(), ERROR_INVALID_VALUE); EXPECT_EQ(ret, 2); EXPECT_EQ(_error_level_test, ERRORLEVEL_WARNING); EXPECT_EQ(_error_test, ERROR_INVALID_VALUE); EXPECT_EQ(error_handler(), _error_handler_test); error_set_handler(handler); { #if BUILD_ENABLE_ERROR_CONTEXT const char context_data[] = "another message"; #endif char context_buffer[512]; string_t contextstr; error_context_clear(); error_context_push(STRING_CONST("test context"), STRING_CONST("some message")); error_context_push(STRING_CONST("foo bar"), 0, 0); error_context_pop(); error_context_pop(); error_context_pop(); error_context_push(STRING_CONST("test context"), STRING_CONST(context_data)); #if BUILD_ENABLE_ERROR_CONTEXT EXPECT_NE(error_context(), 0); EXPECT_EQ(error_context()->depth, 1); EXPECT_CONSTSTRINGEQ(error_context()->frame[0].name, string_const(STRING_CONST("test context"))); EXPECT_EQ(error_context()->frame[0].data.str, context_data); EXPECT_EQ(error_context()->frame[0].data.length, sizeof(context_data) - 1); #endif contextstr = error_context_buffer(context_buffer, 512); #if BUILD_ENABLE_ERROR_CONTEXT EXPECT_NE_MSGFORMAT(string_find_string(STRING_ARGS(contextstr), STRING_CONST("test context"), 0), STRING_NPOS, "context name 'test context' not found in buffer: %s", context_buffer); EXPECT_NE_MSGFORMAT(string_find_string(STRING_ARGS(contextstr), STRING_CONST(context_data), 0), STRING_NPOS, "context data '%s' not found in buffer: %s", context_data, context_buffer); #else EXPECT_EQ(contextstr.length, 0); #endif error_context_clear(); contextstr = error_context_buffer(context_buffer, 512); #if BUILD_ENABLE_ERROR_CONTEXT EXPECT_STRINGEQ(contextstr, string_empty()); #endif } return 0; }
static void* error_test_thread(void) { error_context_t* context = 0; EXPECT_EQ(error(), ERROR_NONE); EXPECT_EQ(error(), ERROR_NONE); error_report(ERRORLEVEL_WARNING, ERROR_ACCESS_DENIED); EXPECT_EQ(error(), ERROR_ACCESS_DENIED); EXPECT_EQ(error(), ERROR_NONE); error_report(ERRORLEVEL_ERROR, ERROR_INVALID_VALUE); EXPECT_EQ(error(), ERROR_INVALID_VALUE); EXPECT_EQ(error(), ERROR_NONE); context = error_context(); if (context) EXPECT_EQ(context->depth, 0); error_context_push(STRING_CONST("error test"), STRING_CONST("data")); context = error_context(); #if BUILD_ENABLE_ERROR_CONTEXT EXPECT_NE(context, 0); EXPECT_EQ(context->depth, 1); EXPECT_CONSTSTRINGEQ(context->frame[0].name, string_const(STRING_CONST("error test"))); EXPECT_CONSTSTRINGEQ(context->frame[0].data, string_const(STRING_CONST("data"))); #else EXPECT_EQ(context, 0); #endif error_context_pop(); context = error_context(); #if BUILD_ENABLE_ERROR_CONTEXT EXPECT_NE(context, 0); EXPECT_EQ(context->depth, 0); #else EXPECT_EQ(context, 0); #endif error_context_push(STRING_CONST("error test"), STRING_CONST("data")); error_context_push(STRING_CONST("another test"), STRING_CONST("more data")); context = error_context(); #if BUILD_ENABLE_ERROR_CONTEXT EXPECT_NE(context, 0); EXPECT_EQ(context->depth, 2); EXPECT_CONSTSTRINGEQ(context->frame[0].name, string_const(STRING_CONST("error test"))); EXPECT_CONSTSTRINGEQ(context->frame[0].data, string_const(STRING_CONST("data"))); EXPECT_CONSTSTRINGEQ(context->frame[1].name, string_const(STRING_CONST("another test"))); EXPECT_CONSTSTRINGEQ(context->frame[1].data, string_const(STRING_CONST("more data"))); #else EXPECT_EQ(context, 0); #endif error_context_pop(); context = error_context(); #if BUILD_ENABLE_ERROR_CONTEXT EXPECT_NE(context, 0); EXPECT_EQ(context->depth, 1); EXPECT_CONSTSTRINGEQ(context->frame[0].name, string_const(STRING_CONST("error test"))); EXPECT_CONSTSTRINGEQ(context->frame[0].data, string_const(STRING_CONST("data"))); #else EXPECT_EQ(context, 0); #endif error_context_pop(); return 0; }
/* return 1 if usable, 0 if not */ static int parse_upsd_conf_args(int numargs, char **arg) { /* everything below here uses up through arg[1] */ if (numargs < 2) return 0; /* MAXAGE <seconds> */ if (!strcmp(arg[0], "MAXAGE")) { maxage = atoi(arg[1]); return 1; } /* MAXCONN <connections> */ if (!strcmp(arg[0], "MAXCONN")) { maxconn = atoi(arg[1]); return 1; } /* STATEPATH <dir> */ if (!strcmp(arg[0], "STATEPATH")) { free(statepath); statepath = xstrdup(arg[1]); return 1; } /* DATAPATH <dir> */ if (!strcmp(arg[0], "DATAPATH")) { free(datapath); datapath = xstrdup(arg[1]); return 1; } /* CERTFILE <dir> */ if (!strcmp(arg[0], "CERTFILE")) { free(certfile); certfile = xstrdup(arg[1]); return 1; } /* ACCEPT <aclname> [<aclname>...] */ if (!strcmp(arg[0], "ACCEPT")) { upslogx(LOG_WARNING, "ACCEPT in upsd.conf is no longer supported - switch to LISTEN"); return 1; } /* REJECT <aclname> [<aclname>...] */ if (!strcmp(arg[0], "REJECT")) { upslogx(LOG_WARNING, "REJECT in upsd.conf is no longer supported - switch to LISTEN"); return 1; } /* LISTEN <address> [<port>] */ if (!strcmp(arg[0], "LISTEN")) { if (numargs < 3) listen_add(arg[1], string_const(PORT)); else listen_add(arg[1], arg[2]); return 1; } /* everything below here uses up through arg[2] */ if (numargs < 3) return 0; /* ACL <aclname> <ip block> */ if (!strcmp(arg[0], "ACL")) { upslogx(LOG_WARNING, "ACL in upsd.conf is no longer supported - switch to LISTEN"); return 1; } /* not recognized */ return 0; }
/*! Normal entry point for all platforms, including Windows console applications */ int main(int argc, char** argv) #endif { int ret; #if !FOUNDATION_PLATFORM_ANDROID && !FOUNDATION_PLATFORM_PNACL _environment_main_args(argc, (const char* const*)argv); #elif FOUNDATION_PLATFORM_PNACL FOUNDATION_UNUSED(instance); #endif ret = main_initialize(); if (ret < 0) return ret; #if FOUNDATION_PLATFORM_POSIX //Set signal handlers { struct sigaction action; memset(&action, 0, sizeof(action)); #if FOUNDATION_COMPILER_CLANG # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wdisabled-macro-expansion" #endif //Signals we process globally action.sa_handler = sighandler; sigaction(SIGKILL, &action, 0); sigaction(SIGTERM, &action, 0); sigaction(SIGQUIT, &action, 0); sigaction(SIGINT, &action, 0); sigaction(SIGABRT, &action, 0); //Ignore sigpipe action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &action, 0); #if FOUNDATION_COMPILER_CLANG # pragma clang diagnostic pop #endif } #endif #if FOUNDATION_PLATFORM_ANDROID if ((ret = android_initialize()) < 0) return ret; #endif #if FOUNDATION_PLATFORM_TIZEN if ((ret = tizen_initialize()) < 0) return ret; #endif #if FOUNDATION_PLATFORM_WINDOWS SetConsoleCtrlHandler(_main_console_handler, TRUE); #endif thread_set_main(); foundation_startup(); #if FOUNDATION_PLATFORM_WINDOWS || FOUNDATION_PLATFORM_LINUX || FOUNDATION_PLATFORM_PNACL system_post_event(FOUNDATIONEVENT_START); #endif #if FOUNDATION_PLATFORM_APPLE # if FOUNDATION_PLATFORM_MACOSX if (!(environment_application()->flags & APPLICATION_UTILITY)) { delegate_start_main_ns_thread(); extern int NSApplicationMain(int argc, char* argv[]); ret = NSApplicationMain(argc, argv); # elif FOUNDATION_PLATFORM_IOS { delegate_start_main_ns_thread(); extern int UIApplicationMain(int argc, char* argv[], void* principalClassName, void* delegateClassName); ret = UIApplicationMain(argc, (char**)argv, 0, 0); # endif //NSApplicationMain and UIApplicationMain never returns though return ret; } #endif #if !FOUNDATION_PLATFORM_IOS # if FOUNDATION_PLATFORM_TIZEN tizen_start_main_thread(); ret = tizen_app_main(argc, argv); # else { string_t name; const application_t* app = environment_application(); { string_const_t vstr = string_from_version_static(app->version); string_const_t aname = app->short_name; if (!aname.length) aname = string_const(STRING_CONST("unknown")); name = string_allocate_format(STRING_CONST("%.*s-%.*s"), (int)aname.length, aname.str, (int)vstr.length, vstr.str); } if (app->dump_callback) crash_guard_set(app->dump_callback, name.str, name.length); if (system_debugger_attached()) ret = main_run(0); else ret = crash_guard(main_run, 0, app->dump_callback, name.str, name.length); string_deallocate(name.str); } # endif main_finalize(); #if FOUNDATION_PLATFORM_ANDROID android_finalize(); #endif #if FOUNDATION_PLATFORM_TIZEN tizen_finalize(); #endif return ret; #endif } #if FOUNDATION_PLATFORM_ANDROID /*! Android native glue entry point */ void android_main(struct android_app * app) { if (!app) return; android_entry(app); real_main(); } #endif #if FOUNDATION_PLATFORM_PNACL /*! PNaCl glue entry points */ PP_EXPORT int32_t PPP_InitializeModule(PP_Module module_id, PPB_GetInterface get_browser) { return pnacl_module_initialize(module_id, get_browser); } PP_EXPORT const void* PPP_GetInterface(const char* interface_name) { return pnacl_module_interface(interface_name, string_length(interface_name)); } PP_EXPORT void PPP_ShutdownModule() { pnacl_module_finalize(); }
static int render_import_shader(stream_t* stream, const uuid_t uuid) { char buffer[1024]; char pathbuf[BUILD_MAX_PATHLEN]; resource_source_t source; resource_platform_t platformdecl = {-1, -1, -1, -1, -1, -1}; uint64_t platform; tick_t timestamp; int ret = 0; resource_source_initialize(&source); resource_source_read(&source, uuid); platform = resource_platform(platformdecl); timestamp = time_system(); while (!stream_eos(stream)) { uuid_t shaderuuid; string_const_t target, ref, fullpath; string_t line = stream_read_line_buffer(stream, buffer, sizeof(buffer), '\n'); string_split(STRING_ARGS(line), STRING_CONST(" \t"), &target, &ref, false); ref = string_strip(STRING_ARGS(ref), STRING_CONST(STRING_WHITESPACE)); shaderuuid = string_to_uuid(STRING_ARGS(ref)); if (uuid_is_null(shaderuuid)) { if (path_is_absolute(STRING_ARGS(ref))) { fullpath = ref; } else { string_t full; string_const_t path = stream_path(stream); path = path_directory_name(STRING_ARGS(path)); full = path_concat(pathbuf, sizeof(pathbuf), STRING_ARGS(path), STRING_ARGS(ref)); full = path_absolute(STRING_ARGS(full), sizeof(pathbuf)); fullpath = string_const(STRING_ARGS(full)); } resource_signature_t sig = resource_import_lookup(STRING_ARGS(fullpath)); if (uuid_is_null(sig.uuid)) { if (!resource_import(STRING_ARGS(fullpath), uuid_null())) { log_warnf(HASH_RESOURCE, WARNING_SUSPICIOUS, STRING_CONST("Unable to import linked shader: %.*s"), STRING_FORMAT(fullpath)); ret = -1; goto finalize; } sig = resource_import_lookup(STRING_ARGS(fullpath)); if (uuid_is_null(sig.uuid)) { log_warnf(HASH_RESOURCE, WARNING_SUSPICIOUS, STRING_CONST("Import linked shader gave no UUID: %.*s"), STRING_FORMAT(fullpath)); ret = -1; goto finalize; } } shaderuuid = sig.uuid; } if (!uuid_is_null(shaderuuid)) { resource_platform_t targetplatformdecl = render_import_parse_target(STRING_ARGS(target), platformdecl); uint64_t targetplatform = resource_platform(targetplatformdecl); if (resource_autoimport_need_update(shaderuuid, targetplatform)) resource_autoimport(shaderuuid); const string_const_t uuidstr = string_from_uuid_static(shaderuuid); resource_source_set(&source, timestamp, HASH_SHADER, targetplatform, STRING_ARGS(uuidstr)); resource_source_set_dependencies(uuid, targetplatform, &shaderuuid, 1); } } resource_source_set(&source, timestamp, HASH_RESOURCE_TYPE, 0, STRING_CONST("shader")); if (!resource_source_write(&source, uuid, false)) { string_const_t uuidstr = string_from_uuid_static(uuid); log_warnf(HASH_RESOURCE, WARNING_SUSPICIOUS, STRING_CONST("Failed writing imported shader: %.*s"), STRING_FORMAT(uuidstr)); ret = -1; goto finalize; } else { string_const_t uuidstr = string_from_uuid_static(uuid); log_infof(HASH_RESOURCE, STRING_CONST("Wrote imported shader: %.*s"), STRING_FORMAT(uuidstr)); } finalize: resource_source_finalize(&source); return 0; }
static lua_result_t lua_do_call_custom(lua_t* env, const char* method, size_t length, lua_arg_t* arg) { lua_State* state; lua_result_t result; int numargs, i; int stacksize; size_t start, next; string_const_t part; state = env->state; stacksize = lua_gettop(state); result = LUA_OK; ++env->calldepth; next = string_find(method, length, '.', 0); if (next != STRING_NPOS) { part = string_const(method, next); lua_getlglobal(state, part.str, part.length); if (lua_isnil(state, -1)) { log_errorf(HASH_LUA, ERROR_INVALID_VALUE, STRING_CONST("Invalid script call, '%.*s' is not set (%.*s)"), STRING_FORMAT(part), (int)length, method); --env->calldepth; lua_pop(state, lua_gettop(state) - stacksize); return LUA_ERROR; } else if (!lua_istable(state, -1)) { log_errorf(HASH_LUA, ERROR_INVALID_VALUE, STRING_CONST("Invalid script call, existing data '%.*s' in '%.*s' is not a table"), STRING_FORMAT(part), (int)length, method); --env->calldepth; lua_pop(state, lua_gettop(state) - stacksize); return LUA_ERROR; } //Top of stack is now table FOUNDATION_ASSERT(lua_istable(state, -1)); ++next; start = next; next = string_find(method, length, '.', next); while (next != STRING_NPOS) { part = string_const(method + start, next - start); lua_pushlstring(state, part.str, part.length); lua_gettable(state, -2); if (lua_isnil(state, -1)) { log_errorf(HASH_LUA, ERROR_INVALID_VALUE, STRING_CONST("Invalid script call, '%.*s' is not set (%.*s)"), STRING_FORMAT(part), (int)next, method); --env->calldepth; lua_pop(state, lua_gettop(state) - stacksize); return LUA_ERROR; } else if (!lua_istable(state, -1)) { log_errorf(HASH_LUA, ERROR_INVALID_VALUE, STRING_CONST("Invalid script call, existing data '%.*s' in '%.*s' is not a table"), STRING_FORMAT(part), (int)next, method); --env->calldepth; lua_pop(state, lua_gettop(state) - stacksize); return LUA_ERROR; } //Top of stack is now table FOUNDATION_ASSERT(lua_istable(state, -1)); ++next; start = next; next = string_find(method, length, '.', next); } part = string_const(method + start, length - start); lua_pushlstring(state, part.str, part.length); lua_gettable(state, -2); } else { lua_getlglobal(state, method, length); } if (lua_isnil(state, -1)) { --env->calldepth; lua_pop(state, lua_gettop(state) - stacksize); //Method does not exist in Lua context log_errorf(HASH_LUA, ERROR_INVALID_VALUE, STRING_CONST("Invalid script call, '%.*s' is not a function"), (int)length, method); return LUA_ERROR; } numargs = 0; if (arg) { numargs = (arg->num < LUA_MAX_ARGS) ? arg->num : LUA_MAX_ARGS; for (i = 0; i < numargs; ++i) { switch (arg->type[i]) { case LUADATA_PTR: lua_pushlightuserdata(state, arg->value[i].ptr); break; case LUADATA_OBJ: lua_pushobject(state, arg->value[i].obj); break; case LUADATA_INT: lua_pushinteger(state, arg->value[i].ival); break; case LUADATA_REAL: lua_pushnumber(state, arg->value[i].val); break; case LUADATA_STR: lua_pushlstring(state, arg->value[i].str, arg->size[i]); break; case LUADATA_BOOL: lua_pushboolean(state, arg->value[i].flag); break; case LUADATA_INTARR: { const int* values = arg->value[i].ptr; lua_newtable(state); for (uint16_t ia = 0; ia < arg->size[i]; ++ia) { lua_pushinteger(state, ia + 1); lua_pushinteger(state, values[ia]); lua_settable(state, -3); } break; } case LUADATA_REALARR: { const real* values = arg->value[i].ptr; lua_newtable(state); for (uint16_t ia = 0; ia < arg->size[i]; ++ia) { lua_pushinteger(state, ia + 1); lua_pushnumber(state, values[ia]); lua_settable(state, -3); } break; } default: --numargs; break; } } } //TODO: Parse return value from call if (lua_pcall(state, numargs, 0, 0) != 0) { string_const_t errmsg = {0, 0}; errmsg.str = lua_tolstring(state, -1, &errmsg.length); log_errorf(HASH_LUA, ERROR_INTERNAL_FAILURE, STRING_CONST("Calling %.*s : %.*s"), (int)length, method, STRING_FORMAT(errmsg)); result = LUA_ERROR; } --env->calldepth; lua_pop(state, lua_gettop(state) - stacksize); return result; }
static int render_import_program(stream_t* stream, const uuid_t uuid) { char buffer[1024]; char pathbuf[BUILD_MAX_PATHLEN]; resource_source_t source; resource_platform_t platformdecl = {-1, -1, -1, -1, -1, -1}; uint64_t platform; tick_t timestamp; int ret = 0; resource_source_initialize(&source); resource_source_read(&source, uuid); platform = resource_platform(platformdecl); timestamp = time_system(); while (!stream_eos(stream)) { string_const_t type, ref; string_const_t fullpath; string_const_t uuidstr; uuid_t shaderuuid; hash_t typehash; string_t line = stream_read_line_buffer(stream, buffer, sizeof(buffer), '\n'); string_split(STRING_ARGS(line), STRING_CONST(" \t"), &type, &ref, false); type = string_strip(STRING_ARGS(type), STRING_CONST(STRING_WHITESPACE)); ref = string_strip(STRING_ARGS(ref), STRING_CONST(STRING_WHITESPACE)); if (!type.length || !ref.length) continue; typehash = hash(STRING_ARGS(type)); if ((typehash != HASH_VERTEXSHADER) && (typehash != HASH_PIXELSHADER)) { log_warnf(HASH_RESOURCE, WARNING_SUSPICIOUS, STRING_CONST("Ignore invalid line: %.*s"), STRING_FORMAT(line)); continue; } shaderuuid = string_to_uuid(STRING_ARGS(ref)); if (uuid_is_null(shaderuuid)) { if (path_is_absolute(STRING_ARGS(ref))) { fullpath = ref; } else { string_t full; string_const_t path = stream_path(stream); path = path_directory_name(STRING_ARGS(path)); full = path_concat(pathbuf, sizeof(pathbuf), STRING_ARGS(path), STRING_ARGS(ref)); full = path_absolute(STRING_ARGS(full), sizeof(pathbuf)); fullpath = string_const(STRING_ARGS(full)); } resource_signature_t sig = resource_import_lookup(STRING_ARGS(fullpath)); if (uuid_is_null(sig.uuid)) { if (!resource_import(STRING_ARGS(fullpath), uuid_null())) { log_warnf(HASH_RESOURCE, WARNING_SUSPICIOUS, STRING_CONST("Unable to import linked shader: %.*s"), STRING_FORMAT(fullpath)); ret = -1; goto finalize; } sig = resource_import_lookup(STRING_ARGS(fullpath)); if (uuid_is_null(sig.uuid)) { log_warnf(HASH_RESOURCE, WARNING_SUSPICIOUS, STRING_CONST("Import linked shader gave no UUID: %.*s"), STRING_FORMAT(fullpath)); ret = -1; goto finalize; } } shaderuuid = sig.uuid; } if (!uuid_is_null(shaderuuid)) { uuidstr = string_from_uuid_static(shaderuuid); resource_source_set(&source, timestamp, typehash, platform, STRING_ARGS(uuidstr)); } } resource_source_set(&source, timestamp, HASH_RESOURCE_TYPE, 0, STRING_CONST("program")); if (!resource_source_write(&source, uuid, false)) { string_const_t uuidstr = string_from_uuid_static(uuid); log_warnf(HASH_RESOURCE, WARNING_SUSPICIOUS, STRING_CONST("Failed writing imported program: %.*s"), STRING_FORMAT(uuidstr)); ret = -1; goto finalize; } else { string_const_t uuidstr = string_from_uuid_static(uuid); log_infof(HASH_RESOURCE, STRING_CONST("Wrote imported program: %.*s"), STRING_FORMAT(uuidstr)); } finalize: resource_source_finalize(&source); return ret; }
lua_result_t lua_do_bind(lua_t* env, const char* property, size_t length, lua_command_t cmd, lua_value_t val) { lua_State* state; int stacksize; size_t start, next; string_const_t part; if (!env || !length) return LUA_ERROR; state = env->state; stacksize = lua_gettop(state); next = string_find(property, length, '.', 0); if (next != STRING_NPOS) { int tables; unsigned int numtables = 0; part = string_const(property, next); lua_getlglobal(state, part.str, part.length); if (lua_isnil(state, -1)) { //Create global table lua_pop(state, 1); lua_newtable(state); lua_pushvalue(state, -1); lua_setlglobal(state, part.str, part.length); log_debugf(HASH_LUA, STRING_CONST("Created global table: %.*s"), STRING_FORMAT(part)); } else if (!lua_istable(state, -1)) { log_errorf(HASH_LUA, ERROR_INVALID_VALUE, STRING_CONST("Invalid script bind call, existing data '%.*s' in '%.*s' is not a table"), STRING_FORMAT(part), (int)length, property); lua_pop(state, lua_gettop(state) - stacksize); return LUA_ERROR; } //Top of stack is now table FOUNDATION_ASSERT(lua_istable(state, -1)); ++next; start = next; ++numtables; next = string_find(property, length, '.', next); while (next != STRING_NPOS) { part = string_const(property + start, next - start); lua_pushlstring(state, part.str, part.length); lua_gettable(state, -2); if (lua_isnil(state, -1)) { //Create sub-table lua_pop(state, 1); lua_newtable(state); lua_pushlstring(state, part.str, part.length); lua_pushvalue(state, -2); lua_settable(state, -4); log_debugf(HASH_LUA, STRING_CONST("Created table: %.*s"), next, property); } else if (!lua_istable(state, -1)) { log_errorf(HASH_LUA, ERROR_INVALID_VALUE, STRING_CONST("Invalid script bind call, existing data '%.*s' in '%.*s' is not a table"), STRING_FORMAT(part), (int)next, property); lua_pop(state, lua_gettop(state) - stacksize); return LUA_ERROR; } //Top of stack is now table FOUNDATION_ASSERT(lua_istable(state, -1)); ++next; start = next; next = string_find(property, length, '.', next); ++numtables; } part = string_const(property + start, length - start); switch (cmd) { case LUACMD_BIND: lua_push_method(state, STRING_ARGS(part), val.fn); break; case LUACMD_BIND_INT: lua_push_integer(state, STRING_ARGS(part), val.ival); break; case LUACMD_BIND_VAL: lua_push_number(state, STRING_ARGS(part), val.val); break; default: break; } tables = lua_gettop(state) - stacksize; lua_pop(state, tables); FOUNDATION_ASSERT(tables == (int)numtables); } else { part = string_const(property, length); switch (cmd) { case LUACMD_BIND: lua_push_method_global(state, STRING_ARGS(part), val.fn); break; case LUACMD_BIND_INT: lua_push_integer_global(state, STRING_ARGS(part), val.ival); break; case LUACMD_BIND_VAL: lua_push_number_global(state, STRING_ARGS(part), val.val); break; default: break; } } return LUA_OK; }