diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 800e0f6357940..4049da9421bc4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -420,6 +420,9 @@ add_sdl_test_executable(testrendercopyex NEEDS_RESOURCES TESTUTILS SOURCES testr add_sdl_test_executable(testmessage SOURCES testmessage.c) add_sdl_test_executable(testdisplayinfo SOURCES testdisplayinfo.c) add_sdl_test_executable(testqsort NONINTERACTIVE SOURCES testqsort.c) +if(EMSCRIPTEN) + target_link_options(testqsort PRIVATE -sALLOW_MEMORY_GROWTH) +endif() add_sdl_test_executable(testbounds NONINTERACTIVE SOURCES testbounds.c) add_sdl_test_executable(testcustomcursor SOURCES testcustomcursor.c) add_sdl_test_executable(testvulkan NO_C90 SOURCES testvulkan.c) diff --git a/test/testqsort.c b/test/testqsort.c index 6230e74657952..4b36969a50d31 100644 --- a/test/testqsort.c +++ b/test/testqsort.c @@ -10,14 +10,29 @@ freely. */ +#ifdef TEST_STDLIB_QSORT +#define _GNU_SOURCE +#include +#endif + #include #include #include +typedef struct { + Uint8 major; + Uint8 minor; + Uint8 micro; +} VersionTuple; + static int a_global_var = 77; +static int (SDLCALL * global_compare_cbfn)(const void *_a, const void *_b); + +static unsigned long arraylens[16] = { 12, 1024 * 100 }; +static unsigned int count_arraylens = 2; static int SDLCALL -num_compare(const void *_a, const void *_b) +compare_int(const void *_a, const void *_b) { const int a = *((const int *)_a); const int b = *((const int *)_b); @@ -25,51 +40,445 @@ num_compare(const void *_a, const void *_b) } static int SDLCALL -num_compare_r(void *userdata, const void *a, const void *b) +compare_float(const void *_a, const void *_b) +{ + const float a = *((const float *)_a); + const float b = *((const float *)_b); + return (a < b) ? -1 : ((a > b) ? 1 : 0); +} + +static int SDLCALL +compare_double(const void *_a, const void *_b) +{ + const double a = *((const double *)_a); + const double b = *((const double *)_b); + return (a < b) ? -1 : ((a > b) ? 1 : 0); +} + +static int SDLCALL +compare_intptr(const void *_a, const void *_b) +{ + const int* a = *((const int **)_a); + const int* b = *((const int **)_b); + return compare_int(a, b); +} + +static int SDLCALL +compare_version(const void *_a, const void *_b) +{ + const VersionTuple *a = ((const VersionTuple *)_a); + const VersionTuple *b = ((const VersionTuple *)_b); + int d; + d = (int)a->major - (int)b->major; + if (d != 0) { + return d; + } + d = (int)a->minor - (int)b->minor; + if (d != 0) { + return d; + } + return (int)a->micro - (int)b->micro; +} + +#ifdef TEST_STDLIB_QSORT +#define SDL_qsort qsort +#define SDL_qsort_r qsort_r +#endif + +static int SDLCALL +#ifdef TEST_STDLIB_QSORT +generic_compare_r(const void *a, const void *b, void *userdata) +#else +generic_compare_r(void *userdata, const void *a, const void *b) +#endif { if (userdata != &a_global_var) { - SDL_Log("Uhoh, invalid userdata during qsort!"); + SDLTest_AssertCheck(userdata == &a_global_var, "User data of callback must be identical to global data"); } - return num_compare(a, b); + return global_compare_cbfn(a, b); } -static void -test_sort(const char *desc, int *nums, const int arraylen) +#define STR2(S) "[" #S "] " +#define STR(S) STR2(S) + +#define TEST_ARRAY_IS_SORTED(TYPE, ARRAY, SIZE, IS_LE) \ + do { \ + size_t sorted_index; \ + Uint64 count_non_sorted = 0; \ + for (sorted_index = 0; sorted_index < (SIZE) - 1; sorted_index++) { \ + if (!IS_LE((ARRAY)[sorted_index], (ARRAY)[sorted_index + 1])) { \ + count_non_sorted += 1; \ + } \ + } \ + SDLTest_AssertCheck(count_non_sorted == 0, \ + STR(TYPE) "Array (size=%d) is sorted (bad count=%" SDL_PRIu64 ")", (SIZE), count_non_sorted); \ + } while (0) + +/* This test is O(n^2), so very slow (a hashmap can speed this up): + * - we cannot trust qsort + * - the arrays can contain duplicate items + * - the arrays are not int + */ +#define TEST_ARRAY_LOST_NO_ELEMENTS(TYPE, ORIGINAL, SORTED, SIZE, IS_SAME) \ + do { \ + size_t original_index; \ + bool *original_seen = SDL_calloc((SIZE), sizeof(bool)); \ + Uint64 lost_count = 0; \ + SDL_assert(original_seen != NULL); \ + for (original_index = 0; original_index < (SIZE); original_index++) { \ + size_t sorted_index; \ + for (sorted_index = 0; sorted_index < (SIZE); sorted_index++) { \ + if (IS_SAME((ORIGINAL)[original_index], (SORTED)[sorted_index])) { \ + original_seen[original_index] = true; \ + break; \ + } \ + } \ + } \ + for (original_index = 0; original_index < (SIZE); original_index++) { \ + if (!original_seen[original_index]) { \ + SDLTest_AssertCheck(original_seen[original_index], \ + STR(TYPE) "Element %d is missing in the sorted array", (int)original_index); \ + lost_count += 1; \ + } \ + } \ + SDLTest_AssertCheck(lost_count == 0, \ + STR(TYPE) "No elements were lost (lost count=%" SDL_PRIu64 ")", lost_count); \ + SDL_free(original_seen); \ + } while (0) + +#define TEST_QSORT_ARRAY_GENERIC(TYPE, ARRAY, SIZE, QSORT_CALL, CHECK_ARRAY_ELEMS, IS_LE, WHAT) \ + do { \ + SDL_memcpy(sorted, (ARRAY), sizeof(TYPE) * (SIZE)); \ + SDLTest_AssertPass(STR(TYPE) "About to call " WHAT "(%d, %d)", \ + (int)(SIZE), (int)sizeof(TYPE)); \ + QSORT_CALL; \ + SDLTest_AssertPass(STR(TYPE) WHAT " finished"); \ + TEST_ARRAY_IS_SORTED(TYPE, sorted, SIZE, IS_LE); \ + SDLTest_AssertPass(STR(TYPE) "Verifying element preservation..."); \ + CHECK_ARRAY_ELEMS(TYPE, sorted, (ARRAY), (SIZE)); \ + } while (0) + +#define TEST_QSORT_ARRAY_QSORT(TYPE, ARRAY, SIZE, COMPARE_CBFN, CHECK_ARRAY_ELEMS, IS_LE) \ + do { \ + SDLTest_AssertPass(STR(TYPE) "Testing SDL_qsort of array with size %u", (unsigned)(SIZE)); \ + global_compare_cbfn = NULL; \ + TEST_QSORT_ARRAY_GENERIC(TYPE, ARRAY, SIZE, \ + SDL_qsort(sorted, (SIZE), sizeof(TYPE), COMPARE_CBFN), \ + CHECK_ARRAY_ELEMS, IS_LE, "SDL_qsort"); \ + } while (0); + +#if defined(SDL_PLATFORM_WINDOWS) && defined(TEST_STDLIB_QSORT) +#define TEST_QSORT_ARRAY_QSORT_R(TYPE, ARRAY, SIZE, COMPARE_CBFN, CHECK_ARRAY_ELEMS, IS_LE) \ + do { \ + SDLTest_AssertPass(STR(TYPE) "qsort_r is not available on current platform"); \ + } while (0) +#else +#define TEST_QSORT_ARRAY_QSORT_R(TYPE, ARRAY, SIZE, COMPARE_CBFN, CHECK_ARRAY_ELEMS, IS_LE) \ + do { \ + SDLTest_AssertPass(STR(TYPE) "Testing SDL_qsort_r of array with size %u", (unsigned)(SIZE)); \ + global_compare_cbfn = (COMPARE_CBFN); \ + TEST_QSORT_ARRAY_GENERIC(TYPE, ARRAY, SIZE, \ + SDL_qsort_r(sorted, (SIZE), sizeof(TYPE), generic_compare_r, &a_global_var), \ + CHECK_ARRAY_ELEMS, IS_LE, "SDL_qsort_r"); \ + } while (0); +#endif + +#define TEST_QSORT_ARRAY(TYPE, ARRAY, SIZE, COMPARE_CBFN, CHECK_ARRAY_ELEMS, IS_LE) \ + do { \ + TYPE *sorted = SDL_calloc((SIZE), sizeof(TYPE)); \ + SDL_assert(sorted != NULL); \ + \ + TEST_QSORT_ARRAY_QSORT(TYPE, ARRAY, SIZE, COMPARE_CBFN, CHECK_ARRAY_ELEMS, IS_LE); \ + \ + TEST_QSORT_ARRAY_QSORT_R(TYPE, ARRAY, SIZE, COMPARE_CBFN, CHECK_ARRAY_ELEMS, IS_LE); \ + \ + SDL_free(sorted); \ + } while (0) + +#define INT_ISLE(A, B) ((A) <= (B)) + +#define INTPTR_ISLE(A, B) (*(A) <= *(B)) + +#define FLOAT_ISLE(A, B) ((A) <= (B)) + +#define DOUBLE_ISLE(A, B) ((A) <= (B)) + +#define VERSION_ISLE(A, B) (compare_version(&(A), &(B)) <= 0) + +#define CHECK_ELEMS_SORTED_ARRAY(TYPE, SORTED, INPUT, SIZE) \ + do { \ + unsigned int check_index; \ + for (check_index = 0; check_index < (SIZE); check_index++) { \ + if ((SORTED)[check_index] != (INPUT)[check_index]) { \ + SDLTest_AssertCheck(false, \ + "sorted[%u] == input[%u]", \ + check_index, check_index); \ + } \ + } \ + } while (0) + +static int SDLCALL qsort_testAlreadySorted(void *arg) { - static int nums_copy[1024 * 100]; - int i; - int prev; + unsigned int iteration; + (void)arg; + + for (iteration = 0; iteration < count_arraylens; iteration++) { + const unsigned int arraylen = arraylens[iteration]; + unsigned int i; + int *ints = SDL_malloc(sizeof(int) * arraylen); + int **intptrs = SDL_malloc(sizeof(int *) * arraylen); + double *doubles = SDL_malloc(sizeof(double) * arraylen); + + for (i = 0; i < arraylen; i++) { + ints[i] = i; + intptrs[i] = &ints[i]; + doubles[i] = (double)i * SDL_PI_D; + } + TEST_QSORT_ARRAY(int, ints, arraylen, compare_int, CHECK_ELEMS_SORTED_ARRAY, INT_ISLE); + TEST_QSORT_ARRAY(int *, intptrs, arraylen, compare_intptr, CHECK_ELEMS_SORTED_ARRAY, INTPTR_ISLE); + TEST_QSORT_ARRAY(double, doubles, arraylen, compare_double, CHECK_ELEMS_SORTED_ARRAY, DOUBLE_ISLE); - SDL_assert(SDL_arraysize(nums_copy) >= arraylen); + SDL_free(ints); + SDL_free(intptrs); + SDL_free(doubles); + } + return TEST_COMPLETED; +} - SDL_Log("test: %s arraylen=%d", desc, arraylen); +#define CHECK_ELEMS_SORTED_ARRAY_EXCEPT_LAST(TYPE, SORTED, INPUT, SIZE) \ + do { \ + unsigned int check_index; \ + for (check_index = 0; check_index < (SIZE) - 1; check_index++) { \ + if (SDL_memcmp(&(SORTED)[check_index + 1], &(INPUT)[check_index], sizeof(TYPE)) != 0) { \ + SDLTest_AssertCheck(false, \ + STR(TYPE) "sorted[%u] == input[%u]", \ + check_index + 1, check_index); \ + } \ + } \ + } while (0) - SDL_memcpy(nums_copy, nums, arraylen * sizeof (*nums)); +static int SDLCALL qsort_testAlreadySortedExceptLast(void *arg) +{ + unsigned int iteration; + (void)arg; - SDL_qsort(nums, arraylen, sizeof(nums[0]), num_compare); - SDL_qsort_r(nums_copy, arraylen, sizeof(nums[0]), num_compare_r, &a_global_var); + for (iteration = 0; iteration < count_arraylens; iteration++) { + const unsigned int arraylen = arraylens[iteration]; + unsigned int i; + int *ints = SDL_malloc(sizeof(int) * arraylen); + int **intptrs = SDL_malloc(sizeof(int *) * arraylen); + double *doubles = SDL_malloc(sizeof(double) * arraylen); + VersionTuple *versions = SDL_calloc(arraylen, sizeof(VersionTuple)); - prev = nums[0]; - for (i = 1; i < arraylen; i++) { - const int val = nums[i]; - const int val2 = nums_copy[i]; - if ((val < prev) || (val != val2)) { - SDL_Log("sort is broken!"); - return; + for (i = 0; i < arraylen; i++) { + ints[i] = i; + intptrs[i] = &ints[i]; + doubles[i] = (double)i * SDL_PI_D; + versions[i].micro = (i + 1) % 256; + versions[i].minor = (i + 1) % (256 * 256) / 256; + versions[i].major = (i + 1) % (256 * 256 * 256) / 256 / 256; } - prev = val; + ints[arraylen - 1] = -1; + doubles[arraylen - 1] = -1.; + versions[arraylen - 1].major = 0; + versions[arraylen - 1].minor = 0; + versions[arraylen - 1].micro = 0; + TEST_QSORT_ARRAY(int, ints, arraylen, compare_int, CHECK_ELEMS_SORTED_ARRAY_EXCEPT_LAST, INT_ISLE); + TEST_QSORT_ARRAY(int *, intptrs, arraylen, compare_intptr, CHECK_ELEMS_SORTED_ARRAY_EXCEPT_LAST, INTPTR_ISLE); + TEST_QSORT_ARRAY(double, doubles, arraylen, compare_double, CHECK_ELEMS_SORTED_ARRAY_EXCEPT_LAST, DOUBLE_ISLE); + TEST_QSORT_ARRAY(VersionTuple, versions, arraylen, compare_version, CHECK_ELEMS_SORTED_ARRAY_EXCEPT_LAST, VERSION_ISLE); + + SDL_free(ints); + SDL_free(intptrs); + SDL_free(doubles); + SDL_free(versions); } + return TEST_COMPLETED; } +#define CHECK_ELEMS_SORTED_ARRAY_REVERSED(TYPE, SORTED, INPUT, SIZE) \ + do { \ + unsigned int check_index; \ + for (check_index = 0; check_index < (SIZE); check_index++) { \ + if (SDL_memcmp(&(SORTED)[check_index], &(INPUT)[(SIZE) - check_index - 1], sizeof(TYPE)) != 0) { \ + SDLTest_AssertCheck(false, \ + STR(TYPE) "sorted[%u] != input[%u]", \ + check_index, (SIZE) - check_index - 1); \ + } \ + } \ + } while (0) + +static int SDLCALL qsort_testReverseSorted(void *arg) +{ + unsigned int iteration; + (void)arg; + + for (iteration = 0; iteration < count_arraylens; iteration++) { + const unsigned int arraylen = arraylens[iteration]; + unsigned int i; + int *ints = SDL_malloc(sizeof(int) * arraylen); + int **intptrs = SDL_malloc(sizeof(int *) * arraylen); + double *doubles = SDL_malloc(sizeof(double) * arraylen); + VersionTuple *versions = SDL_calloc(arraylen, sizeof(VersionTuple)); + + for (i = 0; i < arraylen; i++) { + ints[i] = (arraylen - 1) - i; + intptrs[i] = &ints[i]; + doubles[i] = (double)((arraylen - 1) - i) * SDL_PI_D; + versions[i].micro = ints[i] % 256; + versions[i].minor = ints[i] % (256 * 256) / 256; + versions[i].major = ints[i] % (256 * 256 * 256) / 256 / 256; + } + TEST_QSORT_ARRAY(int, ints, arraylen, compare_int, CHECK_ELEMS_SORTED_ARRAY_REVERSED, INT_ISLE); + TEST_QSORT_ARRAY(int *, intptrs, arraylen, compare_intptr, CHECK_ELEMS_SORTED_ARRAY_REVERSED, INTPTR_ISLE); + TEST_QSORT_ARRAY(double, doubles, arraylen, compare_double, CHECK_ELEMS_SORTED_ARRAY_REVERSED, DOUBLE_ISLE); + TEST_QSORT_ARRAY(VersionTuple, versions, arraylen, compare_version, CHECK_ELEMS_SORTED_ARRAY_REVERSED, VERSION_ISLE); + + SDL_free(ints); + SDL_free(intptrs); + SDL_free(doubles); + SDL_free(versions); + } + return TEST_COMPLETED; +} + +#define MAX_RANDOM_INT_VALUE (1024 * 1024) + +#define CHECK_ELEMS_SORTED_ARRAY_RANDOM_INT(TYPE, SORTED, INPUT, SIZE) \ + do { \ + int *presences = SDL_calloc(MAX_RANDOM_INT_VALUE, sizeof(int)); \ + unsigned int check_index; \ + for (check_index = 0; check_index < (SIZE); check_index++) { \ + presences[(SORTED)[check_index]] += 1; \ + presences[(INPUT)[check_index]] -= 1; \ + } \ + for (check_index = 0; check_index < MAX_RANDOM_INT_VALUE; check_index++) { \ + if (presences[check_index] != 0) { \ + SDLTest_AssertCheck(false, "Value %d appears %s in sorted array", \ + check_index, \ + presences[check_index] > 0 ? "MORE" : "LESS"); \ + } \ + } \ + SDL_free(presences); \ + } while (0) + +#define VERSION_TO_INT(VERSION) (((VERSION).major * 256 + (VERSION).minor) * 256 + (VERSION).micro) +#define INT_VERSION_MAJOR(V) (((V) / (256 * 256) % 256)) +#define INT_VERSION_MINOR(V) (((V) / (256)) % 256) +#define INT_VERSION_MICRO(V) ((V) % 256) + +#define CHECK_ELEMS_SORTED_ARRAY_RANDOM_VERSION(TYPE, SORTED, INPUT, SIZE) \ + do { \ + int *presences = SDL_calloc(256 * 256 * 256, sizeof(int)); \ + unsigned int check_index; \ + for (check_index = 0; check_index < (SIZE); check_index++) { \ + presences[VERSION_TO_INT((SORTED)[check_index])] += 1; \ + presences[VERSION_TO_INT((INPUT)[check_index])] -= 1; \ + } \ + for (check_index = 0; check_index < 256 * 256 * 256; check_index++) { \ + if (presences[check_index] != 0) { \ + SDLTest_AssertCheck(false, STR(TYPE) "Version %d.%d.%d appears %s in sorted array", \ + INT_VERSION_MAJOR(check_index), \ + INT_VERSION_MINOR(check_index), \ + INT_VERSION_MICRO(check_index), \ + presences[check_index] > 0 ? "MORE" : "LESS"); \ + } \ + } \ + SDL_free(presences); \ + } while (0) + +#define CHECK_ELEMS_SORTED_ARRAY_RPS(TYPE, SORTED, INPUT, SIZE) \ + do { \ + int presences[3] = { 0 }; \ + unsigned int check_index; \ + for (check_index = 0; check_index < (SIZE); check_index++) { \ + presences[(SORTED)[check_index]] += 1; \ + presences[(INPUT)[check_index]] -= 1; \ + } \ + for (check_index = 0; check_index < SDL_arraysize(presences); check_index++) { \ + if (presences[check_index] != 0) { \ + SDLTest_AssertCheck(false, STR(TYPE) "%d appeared or disappeared", \ + check_index); \ + } \ + } \ + } while (0) + +#define CHECK_ELEMS_SORTED_ARRAY_RANDOM_NOP(TYPE, SORTED, INPUT, SIZE) \ + SDLTest_AssertPass(STR(TYPE) "Skipping elements presence check") + +static int SDLCALL qsort_testRandomSorted(void *arg) +{ + unsigned int iteration; + (void)arg; + + for (iteration = 0; iteration < count_arraylens; iteration++) { + const unsigned int arraylen = arraylens[iteration]; + unsigned int i; + int *ints = SDL_malloc(sizeof(int) * arraylen); + float *floats = SDL_malloc(sizeof(float) * arraylen); + VersionTuple *versions = SDL_calloc(arraylen, sizeof(VersionTuple)); + + for (i = 0; i < arraylen; i++) { + ints[i] = SDLTest_RandomIntegerInRange(0, MAX_RANDOM_INT_VALUE - 1); + floats[i] = SDLTest_RandomFloat() * SDL_PI_F; + versions[i].micro = SDLTest_RandomIntegerInRange(0, 255); + versions[i].minor = SDLTest_RandomIntegerInRange(0, 255); + versions[i].major = SDLTest_RandomIntegerInRange(0, 255); + } + TEST_QSORT_ARRAY(int, ints, arraylen, compare_int, CHECK_ELEMS_SORTED_ARRAY_RANDOM_INT, INT_ISLE); + TEST_QSORT_ARRAY(float, floats, arraylen, compare_float, CHECK_ELEMS_SORTED_ARRAY_RANDOM_NOP, FLOAT_ISLE); + TEST_QSORT_ARRAY(VersionTuple, versions, arraylen, compare_version, CHECK_ELEMS_SORTED_ARRAY_RANDOM_VERSION, VERSION_ISLE); + + SDL_free(ints); + SDL_free(floats); + SDL_free(versions); + } + return TEST_COMPLETED; +} + +static const SDLTest_TestCaseReference qsortTestAlreadySorted = { + qsort_testAlreadySorted, "qsort_testAlreadySorted", "Test sorting already sorted array", TEST_ENABLED +}; + +static const SDLTest_TestCaseReference qsortTestAlreadySortedExceptLast = { + qsort_testAlreadySortedExceptLast, "qsort_testAlreadySortedExceptLast", "Test sorting nearly sorted array (last item is not in order)", TEST_ENABLED +}; + +static const SDLTest_TestCaseReference qsortTestReverseSorted = { + qsort_testReverseSorted, "qsort_testReverseSorted", "Test sorting an array in reverse order", TEST_ENABLED +}; + +static const SDLTest_TestCaseReference qsortTestRandomSorted = { + qsort_testRandomSorted, "qsort_testRandomSorted", "Test sorting a random array", TEST_ENABLED +}; + +static const SDLTest_TestCaseReference *qsortTests[] = { + &qsortTestAlreadySorted, + &qsortTestAlreadySortedExceptLast, + &qsortTestReverseSorted, + &qsortTestRandomSorted, + NULL +}; + +static SDLTest_TestSuiteReference qsortTestSuite = { + "qsort", + NULL, + qsortTests, + NULL +}; + +static SDLTest_TestSuiteReference *testSuites[] = { + &qsortTestSuite, + NULL +}; + int main(int argc, char *argv[]) { - static int nums[1024 * 100]; - static const int itervals[] = { SDL_arraysize(nums), 12 }; int i; - int iteration; + int result; SDLTest_CommonState *state; - Uint64 seed = 0; - int seed_seen = 0; + SDLTest_TestSuiteRunner *runner; + bool list = false; /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); @@ -77,27 +486,47 @@ int main(int argc, char *argv[]) return 1; } + runner = SDLTest_CreateTestSuiteRunner(state, testSuites); + /* Parse commandline */ for (i = 1; i < argc;) { int consumed; consumed = SDLTest_CommonArg(state, i); if (!consumed) { - if (!seed_seen) { - char *endptr = NULL; - - seed = (Uint64)SDL_strtoull(argv[i], &endptr, 0); - if (endptr != argv[i] && *endptr == '\0') { - seed_seen = 1; - consumed = 1; - } else { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Invalid seed. Use a decimal or hexadecimal number."); - return 1; + + if (SDL_strcasecmp(argv[i], "--array-lengths") == 0) { + count_arraylens = 0; + consumed = 1; + while (argv[i + consumed] && argv[i + consumed][0] != '-') { + char *endptr = NULL; + unsigned int arraylen = (unsigned int)SDL_strtoul(argv[i + 1], &endptr, 10); + if (*endptr != '\0') { + count_arraylens = 0; + break; + } + if (count_arraylens >= SDL_arraysize(arraylens)) { + SDL_LogWarn(SDL_LOG_CATEGORY_TEST, "Dropping array length %d", arraylen); + } else { + arraylens[count_arraylens] = arraylen; + } + count_arraylens++; + consumed++; + } + if (consumed == 0) { + SDL_LogError(SDL_LOG_CATEGORY_TEST, "--array-lengths needs positive int numbers"); } + } else if (SDL_strcasecmp(argv[i], "--list") == 0) { + consumed = 1; + list = true; } } if (consumed <= 0) { - static const char *options[] = { "[seed]", NULL }; + static const char *options[] = { + "[--list]", + "[--array-lengths N1 [N2 [N3 [...]]]", + NULL + }; SDLTest_CommonLogUsage(state, argv[0], options); return 1; } @@ -105,38 +534,25 @@ int main(int argc, char *argv[]) i += consumed; } - if (!seed_seen) { - seed = SDL_GetPerformanceCounter(); - } - SDL_Log("Using random seed 0x%" SDL_PRIx64, seed); - - for (iteration = 0; iteration < SDL_arraysize(itervals); iteration++) { - const int arraylen = itervals[iteration]; - - for (i = 0; i < arraylen; i++) { - nums[i] = i; - } - test_sort("already sorted", nums, arraylen); - - for (i = 0; i < arraylen; i++) { - nums[i] = i; - } - nums[arraylen - 1] = -1; - test_sort("already sorted except last element", nums, arraylen); - - for (i = 0; i < arraylen; i++) { - nums[i] = (arraylen - 1) - i; - } - test_sort("reverse sorted", nums, arraylen); - - for (i = 0; i < arraylen; i++) { - nums[i] = SDL_rand_r(&seed, 1000000); + /* List all suites. */ + if (list) { + int suiteCounter; + for (suiteCounter = 0; testSuites[suiteCounter]; ++suiteCounter) { + int testCounter; + SDLTest_TestSuiteReference *testSuite = testSuites[suiteCounter]; + SDL_Log("Test suite: %s", testSuite->name); + for (testCounter = 0; testSuite->testCases[testCounter]; ++testCounter) { + const SDLTest_TestCaseReference *testCase = testSuite->testCases[testCounter]; + SDL_Log(" test: %s%s", testCase->name, testCase->enabled ? "" : " (disabled)"); + } } - test_sort("random sorted", nums, arraylen); + result = 0; + } else { + result = SDLTest_ExecuteTestSuiteRunner(runner); } SDL_Quit(); + SDLTest_DestroyTestSuiteRunner(runner); SDLTest_CommonDestroyState(state); - - return 0; + return result; }