| /** |
| * Properties test suite |
| */ |
| |
| #include <SDL3/SDL.h> |
| #include <SDL3/SDL_test.h> |
| #include "testautomation_suites.h" |
| |
| /* Test case functions */ |
| |
| /** |
| * Test basic functionality |
| */ |
| static void SDLCALL count_properties(void *userdata, SDL_PropertiesID props, const char *name) |
| { |
| int *count = (int *)userdata; |
| ++(*count); |
| } |
| static void SDLCALL count_foo_properties(void *userdata, SDL_PropertiesID props, const char *name) |
| { |
| int *count = (int *)userdata; |
| if (SDL_strcmp(name, "foo") == 0) { |
| ++(*count); |
| } |
| } |
| static int SDLCALL properties_testBasic(void *arg) |
| { |
| SDL_PropertiesID props; |
| char key[2], expected_value[2]; |
| SDL_PropertyType type; |
| void *value; |
| const char *value_string; |
| Sint64 value_number; |
| float value_float; |
| bool value_bool; |
| int i, result, count; |
| |
| props = SDL_CreateProperties(); |
| SDLTest_AssertPass("Call to SDL_CreateProperties()"); |
| SDLTest_AssertCheck(props != 0, |
| "Verify props were created, got: %" SDL_PRIu32, props); |
| |
| for (i = 0; i < 10; ++i) { |
| SDL_snprintf(key, SDL_arraysize(key), "%c", 'a' + i); |
| SDL_snprintf(expected_value, SDL_arraysize(expected_value), "%c", 'a' + i); |
| result = SDL_SetPointerProperty(props, key, expected_value); |
| SDLTest_AssertPass("Call to SDL_SetPointerProperty()"); |
| SDLTest_AssertCheck(result == true, |
| "Verify property value was set, got: %d", result); |
| value = SDL_GetPointerProperty(props, key, NULL); |
| SDLTest_AssertPass("Call to SDL_GetPointerProperty()"); |
| SDLTest_AssertCheck(value && SDL_strcmp((const char *)value, expected_value) == 0, |
| "Verify property value was set, got %s, expected %s", value ? (const char *)value : "NULL", expected_value); |
| } |
| |
| count = 0; |
| SDL_EnumerateProperties(props, count_properties, &count); |
| SDLTest_AssertCheck(count == 10, |
| "Verify property count, expected 10, got: %d", count); |
| |
| for (i = 0; i < 10; ++i) { |
| SDL_snprintf(key, SDL_arraysize(key), "%c", 'a' + i); |
| result = SDL_SetPointerProperty(props, key, NULL); |
| SDLTest_AssertPass("Call to SDL_SetPointerProperty(NULL)"); |
| SDLTest_AssertCheck(result == true, |
| "Verify property value was set, got: %d", result); |
| value = SDL_GetPointerProperty(props, key, NULL); |
| SDLTest_AssertPass("Call to SDL_GetPointerProperty()"); |
| SDLTest_AssertCheck(value == NULL, |
| "Verify property value was set, got %s, expected NULL", (const char *)value); |
| } |
| |
| count = 0; |
| SDL_EnumerateProperties(props, count_properties, &count); |
| SDLTest_AssertCheck(count == 0, |
| "Verify property count, expected 0, got: %d", count); |
| |
| /* Check default values */ |
| value = SDL_GetPointerProperty(props, "foo", (void *)0xabcd); |
| SDLTest_AssertCheck(value == (void *)0xabcd, |
| "Verify property, expected 0xabcd, got: %p", value); |
| value_string = SDL_GetStringProperty(props, "foo", "abcd"); |
| SDLTest_AssertCheck(value_string && SDL_strcmp(value_string, "abcd") == 0, |
| "Verify string property, expected abcd, got: %s", value_string); |
| value_number = SDL_GetNumberProperty(props, "foo", 1234); |
| SDLTest_AssertCheck(value_number == 1234, |
| "Verify number property, expected 1234, got: %" SDL_PRIu64, value_number); |
| value_float = SDL_GetFloatProperty(props, "foo", 1234.0f); |
| SDLTest_AssertCheck(value_float == 1234.0f, |
| "Verify float property, expected 1234, got: %f", value_float); |
| value_bool = SDL_GetBooleanProperty(props, "foo", true); |
| SDLTest_AssertCheck(value_bool == true, |
| "Verify boolean property, expected true, got: %s", value_bool ? "true" : "false"); |
| |
| /* Check data value */ |
| SDLTest_AssertPass("Call to SDL_SetPointerProperty(\"foo\", 0x01)"); |
| SDL_SetPointerProperty(props, "foo", (void *)0x01); |
| type = SDL_GetPropertyType(props, "foo"); |
| SDLTest_AssertCheck(type == SDL_PROPERTY_TYPE_POINTER, |
| "Verify property type, expected %d, got: %d", SDL_PROPERTY_TYPE_POINTER, type); |
| value = SDL_GetPointerProperty(props, "foo", NULL); |
| SDLTest_AssertCheck(value == (void *)0x01, |
| "Verify property, expected 0x01, got: %p", value); |
| value_string = SDL_GetStringProperty(props, "foo", NULL); |
| SDLTest_AssertCheck(value_string == NULL, |
| "Verify string property, expected NULL, got: %s", value_string); |
| value_number = SDL_GetNumberProperty(props, "foo", 0); |
| SDLTest_AssertCheck(value_number == 0, |
| "Verify number property, expected 0, got: %" SDL_PRIu64, value_number); |
| value_float = SDL_GetFloatProperty(props, "foo", 0.0f); |
| SDLTest_AssertCheck(value_float == 0.0f, |
| "Verify float property, expected 0, got: %f", value_float); |
| value_bool = SDL_GetBooleanProperty(props, "foo", false); |
| SDLTest_AssertCheck(value_bool == false, |
| "Verify boolean property, expected false, got: %s", value_bool ? "true" : "false"); |
| |
| /* Check string value */ |
| SDLTest_AssertPass("Call to SDL_SetStringProperty(\"foo\", \"bar\")"); |
| SDL_SetStringProperty(props, "foo", "bar"); |
| type = SDL_GetPropertyType(props, "foo"); |
| SDLTest_AssertCheck(type == SDL_PROPERTY_TYPE_STRING, |
| "Verify property type, expected %d, got: %d", SDL_PROPERTY_TYPE_STRING, type); |
| value = SDL_GetPointerProperty(props, "foo", NULL); |
| SDLTest_AssertCheck(value == NULL, |
| "Verify property, expected NULL, got: %p", value); |
| value_string = SDL_GetStringProperty(props, "foo", NULL); |
| SDLTest_AssertCheck(value_string != NULL && SDL_strcmp(value_string, "bar") == 0, |
| "Verify string property, expected bar, got: %s", value_string); |
| value_number = SDL_GetNumberProperty(props, "foo", 0); |
| SDLTest_AssertCheck(value_number == 0, |
| "Verify number property, expected 0, got: %" SDL_PRIu64, value_number); |
| value_float = SDL_GetFloatProperty(props, "foo", 0.0f); |
| SDLTest_AssertCheck(value_float == 0.0f, |
| "Verify float property, expected 0, got: %f", value_float); |
| value_bool = SDL_GetBooleanProperty(props, "foo", false); |
| SDLTest_AssertCheck(value_bool == true, |
| "Verify boolean property, expected true, got: %s", value_bool ? "true" : "false"); |
| |
| /* Check number value */ |
| SDLTest_AssertPass("Call to SDL_SetNumberProperty(\"foo\", 1)"); |
| SDL_SetNumberProperty(props, "foo", 1); |
| type = SDL_GetPropertyType(props, "foo"); |
| SDLTest_AssertCheck(type == SDL_PROPERTY_TYPE_NUMBER, |
| "Verify property type, expected %d, got: %d", SDL_PROPERTY_TYPE_NUMBER, type); |
| value = SDL_GetPointerProperty(props, "foo", NULL); |
| SDLTest_AssertCheck(value == NULL, |
| "Verify property, expected NULL, got: %p", value); |
| value_string = SDL_GetStringProperty(props, "foo", NULL); |
| SDLTest_AssertCheck(value_string && SDL_strcmp(value_string, "1") == 0, |
| "Verify string property, expected 1, got: %s", value_string); |
| value_number = SDL_GetNumberProperty(props, "foo", 0); |
| SDLTest_AssertCheck(value_number == 1, |
| "Verify number property, expected 1, got: %" SDL_PRIu64, value_number); |
| value_float = SDL_GetFloatProperty(props, "foo", 0.0f); |
| SDLTest_AssertCheck(value_float == 1.0f, |
| "Verify float property, expected 1, got: %f", value_float); |
| value_bool = SDL_GetBooleanProperty(props, "foo", false); |
| SDLTest_AssertCheck(value_bool == true, |
| "Verify boolean property, expected true, got: %s", value_bool ? "true" : "false"); |
| |
| /* Check float value */ |
| SDLTest_AssertPass("Call to SDL_SetFloatProperty(\"foo\", 1)"); |
| SDL_SetFloatProperty(props, "foo", 1.75f); |
| type = SDL_GetPropertyType(props, "foo"); |
| SDLTest_AssertCheck(type == SDL_PROPERTY_TYPE_FLOAT, |
| "Verify property type, expected %d, got: %d", SDL_PROPERTY_TYPE_FLOAT, type); |
| value = SDL_GetPointerProperty(props, "foo", NULL); |
| SDLTest_AssertCheck(value == NULL, |
| "Verify property, expected NULL, got: %p", value); |
| value_string = SDL_GetStringProperty(props, "foo", NULL); |
| SDLTest_AssertCheck(value_string && SDL_strcmp(value_string, "1.750000") == 0, |
| "Verify string property, expected 1.750000, got: %s", value_string); |
| value_number = SDL_GetNumberProperty(props, "foo", 0); |
| SDLTest_AssertCheck(value_number == 2, |
| "Verify number property, expected 2, got: %" SDL_PRIu64, value_number); |
| value_float = SDL_GetFloatProperty(props, "foo", 0.0f); |
| SDLTest_AssertCheck(value_float == 1.75f, |
| "Verify float property, expected 1.75, got: %f", value_float); |
| value_bool = SDL_GetBooleanProperty(props, "foo", false); |
| SDLTest_AssertCheck(value_bool == true, |
| "Verify boolean property, expected true, got: %s", value_bool ? "true" : "false"); |
| |
| /* Check boolean value */ |
| SDLTest_AssertPass("Call to SDL_SetBooleanProperty(\"foo\", true)"); |
| SDL_SetBooleanProperty(props, "foo", 3); /* Note we're testing non-true/false value here */ |
| type = SDL_GetPropertyType(props, "foo"); |
| SDLTest_AssertCheck(type == SDL_PROPERTY_TYPE_BOOLEAN, |
| "Verify property type, expected %d, got: %d", SDL_PROPERTY_TYPE_BOOLEAN, type); |
| value = SDL_GetPointerProperty(props, "foo", NULL); |
| SDLTest_AssertCheck(value == NULL, |
| "Verify property, expected NULL, got: %p", value); |
| value_string = SDL_GetStringProperty(props, "foo", NULL); |
| SDLTest_AssertCheck(value_string && SDL_strcmp(value_string, "true") == 0, |
| "Verify string property, expected true, got: %s", value_string); |
| value_number = SDL_GetNumberProperty(props, "foo", 0); |
| SDLTest_AssertCheck(value_number == 1, |
| "Verify number property, expected 1, got: %" SDL_PRIu64, value_number); |
| value_float = SDL_GetFloatProperty(props, "foo", 0.0f); |
| SDLTest_AssertCheck(value_float == 1.0f, |
| "Verify float property, expected 1, got: %f", value_float); |
| value_bool = SDL_GetBooleanProperty(props, "foo", false); |
| SDLTest_AssertCheck(value_bool == true, |
| "Verify boolean property, expected true, got: %s", value_bool ? "true" : "false"); |
| |
| /* Make sure we have exactly one property named foo */ |
| count = 0; |
| SDL_EnumerateProperties(props, count_foo_properties, &count); |
| SDLTest_AssertCheck(count == 1, |
| "Verify foo property count, expected 1, got: %d", count); |
| |
| SDL_DestroyProperties(props); |
| |
| return TEST_COMPLETED; |
| } |
| |
| /** |
| * Test copy functionality |
| */ |
| static void SDLCALL copy_cleanup(void *userdata, void *value) |
| { |
| } |
| static int SDLCALL properties_testCopy(void *arg) |
| { |
| SDL_PropertiesID a, b; |
| int num; |
| const char *string; |
| void *data; |
| int result; |
| |
| a = SDL_CreateProperties(); |
| SDL_SetNumberProperty(a, "num", 1); |
| SDL_SetStringProperty(a, "string", "foo"); |
| SDL_SetPointerProperty(a, "data", &a); |
| SDL_SetPointerPropertyWithCleanup(a, "cleanup", &a, copy_cleanup, &a); |
| |
| b = SDL_CreateProperties(); |
| SDL_SetNumberProperty(b, "num", 2); |
| |
| SDLTest_AssertPass("Call to SDL_CopyProperties(a, 0)"); |
| result = SDL_CopyProperties(a, 0); |
| SDLTest_AssertCheck(result == false, |
| "SDL_CopyProperties() result, got %d, expected false", result); |
| |
| SDLTest_AssertPass("Call to SDL_CopyProperties(0, b)"); |
| result = SDL_CopyProperties(0, b); |
| SDLTest_AssertCheck(result == false, |
| "SDL_CopyProperties() result, got %d, expected false", result); |
| |
| SDLTest_AssertPass("Call to SDL_CopyProperties(a, b)"); |
| result = SDL_CopyProperties(a, b); |
| SDLTest_AssertCheck(result == true, |
| "SDL_CopyProperties() result, got %d, expected true", result); |
| |
| SDL_DestroyProperties(a); |
| |
| num = (int)SDL_GetNumberProperty(b, "num", 0); |
| SDLTest_AssertCheck(num == 1, |
| "Checking number property, got %d, expected 1", num); |
| |
| string = SDL_GetStringProperty(b, "string", NULL); |
| SDLTest_AssertCheck(string && SDL_strcmp(string, "foo") == 0, |
| "Checking string property, got \"%s\", expected \"foo\"", string); |
| |
| data = SDL_GetPointerProperty(b, "data", NULL); |
| SDLTest_AssertCheck(data == &a, |
| "Checking data property, got %p, expected %p", data, &a); |
| |
| data = SDL_GetPointerProperty(b, "cleanup", NULL); |
| SDLTest_AssertCheck(data == NULL, |
| "Checking cleanup property, got %p, expected NULL", data); |
| |
| SDL_DestroyProperties(b); |
| |
| return TEST_COMPLETED; |
| } |
| |
| /** |
| * Test cleanup functionality |
| */ |
| static void SDLCALL cleanup(void *userdata, void *value) |
| { |
| int *count = (int *)userdata; |
| ++(*count); |
| } |
| static int SDLCALL properties_testCleanup(void *arg) |
| { |
| SDL_PropertiesID props; |
| char key[2], expected_value[2]; |
| int i, count; |
| |
| props = SDL_CreateProperties(); |
| |
| SDLTest_AssertPass("Call to SDL_SetPointerProperty(cleanup)"); |
| count = 0; |
| SDL_SetPointerPropertyWithCleanup(props, "a", "0", cleanup, &count); |
| SDL_ClearProperty(props, "a"); |
| SDLTest_AssertCheck(count == 1, |
| "Verify cleanup for deleting property, got %d, expected 1", count); |
| |
| SDLTest_AssertPass("Call to SDL_DestroyProperties()"); |
| count = 0; |
| for (i = 0; i < 10; ++i) { |
| SDL_snprintf(key, SDL_arraysize(key), "%c", 'a' + i); |
| SDL_snprintf(expected_value, SDL_arraysize(expected_value), "%c", 'a' + i); |
| SDL_SetPointerPropertyWithCleanup(props, key, expected_value, cleanup, &count); |
| } |
| SDL_DestroyProperties(props); |
| SDLTest_AssertCheck(count == 10, |
| "Verify cleanup for destroying properties, got %d, expected 10", count); |
| |
| return TEST_COMPLETED; |
| } |
| |
| /** |
| * Test locking functionality |
| */ |
| struct properties_thread_data |
| { |
| bool done; |
| SDL_PropertiesID props; |
| }; |
| static int SDLCALL properties_thread(void *arg) |
| { |
| struct properties_thread_data *data = (struct properties_thread_data *)arg; |
| |
| while (!data->done) { |
| SDL_LockProperties(data->props); |
| SDL_SetPointerProperty(data->props, "a", "thread_loop"); |
| SDL_UnlockProperties(data->props); |
| } |
| SDL_LockProperties(data->props); |
| SDL_SetPointerProperty(data->props, "a", "thread_done"); |
| SDL_UnlockProperties(data->props); |
| return 0; |
| } |
| static int SDLCALL properties_testLocking(void *arg) |
| { |
| struct properties_thread_data data; |
| SDL_Thread *thread; |
| void *value; |
| |
| SDLTest_AssertPass("Testing property locking"); |
| data.done = false; |
| data.props = SDL_CreateProperties(); |
| SDLTest_AssertPass("Setting property to 'init'"); |
| SDL_SetPointerProperty(data.props, "a", "init"); |
| thread = SDL_CreateThread(properties_thread, "properties_thread", &data); |
| if (thread) { |
| SDLTest_AssertPass("Waiting for property to change to 'thread_loop'"); |
| for ( ; ; ) |
| { |
| SDL_Delay(10); |
| SDL_LockProperties(data.props); |
| value = SDL_GetPointerProperty(data.props, "a", NULL); |
| SDL_UnlockProperties(data.props); |
| |
| if (!value || SDL_strcmp((const char *)value, "thread_loop") == 0) { |
| break; |
| } |
| } |
| SDLTest_AssertCheck(value && SDL_strcmp((const char *)value, "thread_loop") == 0, |
| "After thread loop, property is %s, expected 'thread_loop'", value ? (const char *)value : "NULL"); |
| |
| SDLTest_AssertPass("Setting property to 'main'"); |
| SDL_LockProperties(data.props); |
| SDL_SetPointerProperty(data.props, "a", "main"); |
| SDL_Delay(100); |
| value = SDL_GetPointerProperty(data.props, "a", NULL); |
| SDLTest_AssertCheck(value && SDL_strcmp((const char *)value, "main") == 0, |
| "After 100ms sleep, property is %s, expected 'main'", value ? (const char *)value : "NULL"); |
| SDL_UnlockProperties(data.props); |
| |
| data.done = true; |
| SDL_WaitThread(thread, NULL); |
| |
| value = SDL_GetPointerProperty(data.props, "a", NULL); |
| SDLTest_AssertCheck(value && SDL_strcmp((const char *)value, "thread_done") == 0, |
| "After thread complete, property is %s, expected 'thread_done'", value ? (const char *)value : "NULL"); |
| } |
| SDL_DestroyProperties(data.props); |
| |
| return TEST_COMPLETED; |
| } |
| |
| /* ================= Test References ================== */ |
| |
| /* Properties test cases */ |
| static const SDLTest_TestCaseReference propertiesTestBasic = { |
| properties_testBasic, "properties_testBasic", "Test basic property functionality", TEST_ENABLED |
| }; |
| |
| static const SDLTest_TestCaseReference propertiesTestCopy = { |
| properties_testCopy, "properties_testCopy", "Test property copy functionality", TEST_ENABLED |
| }; |
| |
| static const SDLTest_TestCaseReference propertiesTestCleanup = { |
| properties_testCleanup, "properties_testCleanup", "Test property cleanup functionality", TEST_ENABLED |
| }; |
| |
| static const SDLTest_TestCaseReference propertiesTestLocking = { |
| properties_testLocking, "properties_testLocking", "Test property locking functionality", TEST_ENABLED |
| }; |
| |
| /* Sequence of Properties test cases */ |
| static const SDLTest_TestCaseReference *propertiesTests[] = { |
| &propertiesTestBasic, |
| &propertiesTestCopy, |
| &propertiesTestCleanup, |
| &propertiesTestLocking, |
| NULL |
| }; |
| |
| /* Properties test suite (global) */ |
| SDLTest_TestSuiteReference propertiesTestSuite = { |
| "Properties", |
| NULL, |
| propertiesTests, |
| NULL |
| }; |