Merge commit 'dec0d4ec4153bf9fc2b78ae6c2df45b6ea8dde7a' as 'external/sdl/SDL'
This commit is contained in:
157
external/sdl/SDL/src/test/SDL_test_assert.c
vendored
Normal file
157
external/sdl/SDL/src/test/SDL_test_assert.c
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Used by the test framework and test cases.
|
||||
|
||||
*/
|
||||
#include <SDL3/SDL_test.h>
|
||||
|
||||
/* Enable to have color in logs */
|
||||
#if 1
|
||||
#define COLOR_RED "\033[0;31m"
|
||||
#define COLOR_GREEN "\033[0;32m"
|
||||
#define COLOR_YELLOW "\033[0;93m"
|
||||
#define COLOR_BLUE "\033[0;94m"
|
||||
#define COLOR_END "\033[0m"
|
||||
#else
|
||||
#define COLOR_RED ""
|
||||
#define COLOR_GREEN ""
|
||||
#define COLOR_BLUE ""
|
||||
#define COLOR_YELLOW ""
|
||||
#define COLOR_END ""
|
||||
#endif
|
||||
|
||||
/* Assert check message format */
|
||||
#define SDLTEST_ASSERT_CHECK_FORMAT "Assert '%s': %s"
|
||||
|
||||
/* Assert summary message format */
|
||||
#define SDLTEST_ASSERT_SUMMARY_FORMAT "Assert Summary: Total=%d " COLOR_GREEN "Passed=%d" COLOR_END " " COLOR_RED "Failed=%d" COLOR_END
|
||||
#define SDLTEST_ASSERT_SUMMARY_FORMAT_OK "Assert Summary: Total=%d " COLOR_GREEN "Passed=%d" COLOR_END " " COLOR_GREEN "Failed=%d" COLOR_END
|
||||
|
||||
/* ! \brief counts the failed asserts */
|
||||
static int SDLTest_AssertsFailed = 0;
|
||||
|
||||
/* ! \brief counts the passed asserts */
|
||||
static int SDLTest_AssertsPassed = 0;
|
||||
|
||||
/*
|
||||
* Assert that logs and break execution flow on failures (i.e. for harness errors).
|
||||
*/
|
||||
void SDLTest_Assert(int assertCondition, SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...)
|
||||
{
|
||||
va_list list;
|
||||
char logMessage[SDLTEST_MAX_LOGMESSAGE_LENGTH];
|
||||
|
||||
/* Print assert description into a buffer */
|
||||
SDL_memset(logMessage, 0, SDLTEST_MAX_LOGMESSAGE_LENGTH);
|
||||
va_start(list, assertDescription);
|
||||
(void)SDL_vsnprintf(logMessage, SDLTEST_MAX_LOGMESSAGE_LENGTH - 1, assertDescription, list);
|
||||
va_end(list);
|
||||
|
||||
/* Log, then assert and break on failure */
|
||||
SDL_assert((SDLTest_AssertCheck(assertCondition, "%s", logMessage)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Assert that logs but does not break execution flow on failures (i.e. for test cases).
|
||||
*/
|
||||
int SDLTest_AssertCheck(int assertCondition, SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...)
|
||||
{
|
||||
va_list list;
|
||||
char logMessage[SDLTEST_MAX_LOGMESSAGE_LENGTH];
|
||||
|
||||
/* Print assert description into a buffer */
|
||||
SDL_memset(logMessage, 0, SDLTEST_MAX_LOGMESSAGE_LENGTH);
|
||||
va_start(list, assertDescription);
|
||||
(void)SDL_vsnprintf(logMessage, SDLTEST_MAX_LOGMESSAGE_LENGTH - 1, assertDescription, list);
|
||||
va_end(list);
|
||||
|
||||
/* Log pass or fail message */
|
||||
if (assertCondition == ASSERT_FAIL) {
|
||||
SDLTest_AssertsFailed++;
|
||||
SDLTest_LogError(SDLTEST_ASSERT_CHECK_FORMAT, logMessage, COLOR_RED "Failed" COLOR_END);
|
||||
} else {
|
||||
SDLTest_AssertsPassed++;
|
||||
SDLTest_Log(SDLTEST_ASSERT_CHECK_FORMAT, logMessage, COLOR_GREEN "Passed" COLOR_END);
|
||||
}
|
||||
|
||||
return assertCondition;
|
||||
}
|
||||
|
||||
/*
|
||||
* Explicitly passing Assert that logs (i.e. for test cases).
|
||||
*/
|
||||
void SDLTest_AssertPass(SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...)
|
||||
{
|
||||
va_list list;
|
||||
char logMessage[SDLTEST_MAX_LOGMESSAGE_LENGTH];
|
||||
|
||||
/* Print assert description into a buffer */
|
||||
SDL_memset(logMessage, 0, SDLTEST_MAX_LOGMESSAGE_LENGTH);
|
||||
va_start(list, assertDescription);
|
||||
(void)SDL_vsnprintf(logMessage, SDLTEST_MAX_LOGMESSAGE_LENGTH - 1, assertDescription, list);
|
||||
va_end(list);
|
||||
|
||||
/* Log pass message */
|
||||
SDLTest_AssertsPassed++;
|
||||
SDLTest_Log(SDLTEST_ASSERT_CHECK_FORMAT, logMessage, COLOR_GREEN "Passed" COLOR_END);
|
||||
}
|
||||
|
||||
/*
|
||||
* Resets the assert summary counters to zero.
|
||||
*/
|
||||
void SDLTest_ResetAssertSummary(void)
|
||||
{
|
||||
SDLTest_AssertsPassed = 0;
|
||||
SDLTest_AssertsFailed = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Logs summary of all assertions (total, pass, fail) since last reset
|
||||
* as INFO (failed==0) or ERROR (failed > 0).
|
||||
*/
|
||||
void SDLTest_LogAssertSummary(void)
|
||||
{
|
||||
int totalAsserts = SDLTest_AssertsPassed + SDLTest_AssertsFailed;
|
||||
if (SDLTest_AssertsFailed == 0) {
|
||||
SDLTest_Log(SDLTEST_ASSERT_SUMMARY_FORMAT_OK, totalAsserts, SDLTest_AssertsPassed, SDLTest_AssertsFailed);
|
||||
} else {
|
||||
SDLTest_LogError(SDLTEST_ASSERT_SUMMARY_FORMAT, totalAsserts, SDLTest_AssertsPassed, SDLTest_AssertsFailed);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts the current assert state into a test result
|
||||
*/
|
||||
int SDLTest_AssertSummaryToTestResult(void)
|
||||
{
|
||||
if (SDLTest_AssertsFailed > 0) {
|
||||
return TEST_RESULT_FAILED;
|
||||
} else {
|
||||
if (SDLTest_AssertsPassed > 0) {
|
||||
return TEST_RESULT_PASSED;
|
||||
} else {
|
||||
return TEST_RESULT_NO_ASSERT;
|
||||
}
|
||||
}
|
||||
}
|
2623
external/sdl/SDL/src/test/SDL_test_common.c
vendored
Normal file
2623
external/sdl/SDL/src/test/SDL_test_common.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
113
external/sdl/SDL/src/test/SDL_test_compare.c
vendored
Normal file
113
external/sdl/SDL/src/test/SDL_test_compare.c
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Based on automated SDL_Surface tests originally written by Edgar Simo 'bobbens'.
|
||||
|
||||
Rewritten for test lib by Andreas Schiffler.
|
||||
|
||||
*/
|
||||
#include <SDL3/SDL_test.h>
|
||||
|
||||
#define FILENAME_SIZE 128
|
||||
|
||||
/* Counter for _CompareSurface calls; used for filename creation when comparisons fail */
|
||||
static int _CompareSurfaceCount = 0;
|
||||
|
||||
/* Compare surfaces */
|
||||
int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, int allowable_error)
|
||||
{
|
||||
int ret;
|
||||
int i, j;
|
||||
int bpp, bpp_reference;
|
||||
Uint8 *p, *p_reference;
|
||||
int dist;
|
||||
int sampleErrorX = 0, sampleErrorY = 0, sampleDist = 0;
|
||||
Uint8 R, G, B, A;
|
||||
Uint8 Rd, Gd, Bd, Ad;
|
||||
char imageFilename[FILENAME_SIZE];
|
||||
char referenceFilename[FILENAME_SIZE];
|
||||
|
||||
/* Validate input surfaces */
|
||||
if (surface == NULL || referenceSurface == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Make sure surface size is the same. */
|
||||
if ((surface->w != referenceSurface->w) || (surface->h != referenceSurface->h)) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Sanitize input value */
|
||||
if (allowable_error < 0) {
|
||||
allowable_error = 0;
|
||||
}
|
||||
|
||||
SDL_LockSurface(surface);
|
||||
SDL_LockSurface(referenceSurface);
|
||||
|
||||
ret = 0;
|
||||
bpp = surface->format->BytesPerPixel;
|
||||
bpp_reference = referenceSurface->format->BytesPerPixel;
|
||||
/* Compare image - should be same format. */
|
||||
for (j = 0; j < surface->h; j++) {
|
||||
for (i = 0; i < surface->w; i++) {
|
||||
p = (Uint8 *)surface->pixels + j * surface->pitch + i * bpp;
|
||||
p_reference = (Uint8 *)referenceSurface->pixels + j * referenceSurface->pitch + i * bpp_reference;
|
||||
|
||||
SDL_GetRGBA(*(Uint32 *)p, surface->format, &R, &G, &B, &A);
|
||||
SDL_GetRGBA(*(Uint32 *)p_reference, referenceSurface->format, &Rd, &Gd, &Bd, &Ad);
|
||||
|
||||
dist = 0;
|
||||
dist += (R - Rd) * (R - Rd);
|
||||
dist += (G - Gd) * (G - Gd);
|
||||
dist += (B - Bd) * (B - Bd);
|
||||
|
||||
/* Allow some difference in blending accuracy */
|
||||
if (dist > allowable_error) {
|
||||
ret++;
|
||||
if (ret == 1) {
|
||||
sampleErrorX = i;
|
||||
sampleErrorY = j;
|
||||
sampleDist = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_UnlockSurface(surface);
|
||||
SDL_UnlockSurface(referenceSurface);
|
||||
|
||||
/* Save test image and reference for analysis on failures */
|
||||
_CompareSurfaceCount++;
|
||||
if (ret != 0) {
|
||||
SDLTest_LogError("Comparison of pixels with allowable error of %i failed %i times.", allowable_error, ret);
|
||||
SDLTest_LogError("First detected occurrence at position %i,%i with a squared RGB-difference of %i.", sampleErrorX, sampleErrorY, sampleDist);
|
||||
(void)SDL_snprintf(imageFilename, FILENAME_SIZE - 1, "CompareSurfaces%04d_TestOutput.bmp", _CompareSurfaceCount);
|
||||
SDL_SaveBMP(surface, imageFilename);
|
||||
(void)SDL_snprintf(referenceFilename, FILENAME_SIZE - 1, "CompareSurfaces%04d_Reference.bmp", _CompareSurfaceCount);
|
||||
SDL_SaveBMP(referenceSurface, referenceFilename);
|
||||
SDLTest_LogError("Surfaces from failed comparison saved as '%s' and '%s'", imageFilename, referenceFilename);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
160
external/sdl/SDL/src/test/SDL_test_crc32.c
vendored
Normal file
160
external/sdl/SDL/src/test/SDL_test_crc32.c
vendored
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Used by the test execution component.
|
||||
Original source code contributed by A. Schiffler for GSOC project.
|
||||
|
||||
*/
|
||||
#include <SDL3/SDL_test.h>
|
||||
|
||||
int SDLTest_Crc32Init(SDLTest_Crc32Context *crcContext)
|
||||
{
|
||||
int i, j;
|
||||
CrcUint32 c;
|
||||
|
||||
/* Sanity check context pointer */
|
||||
if (crcContext == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build auxiliary table for parallel byte-at-a-time CRC-32
|
||||
*/
|
||||
#ifdef ORIGINAL_METHOD
|
||||
for (i = 0; i < 256; ++i) {
|
||||
for (c = i << 24, j = 8; j > 0; --j) {
|
||||
c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1);
|
||||
}
|
||||
crcContext->crc32_table[i] = c;
|
||||
}
|
||||
#else
|
||||
for (i = 0; i < 256; i++) {
|
||||
c = i;
|
||||
for (j = 8; j > 0; j--) {
|
||||
if (c & 1) {
|
||||
c = (c >> 1) ^ CRC32_POLY;
|
||||
} else {
|
||||
c >>= 1;
|
||||
}
|
||||
}
|
||||
crcContext->crc32_table[i] = c;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Complete CRC32 calculation on a memory block */
|
||||
int SDLTest_Crc32Calc(SDLTest_Crc32Context *crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32)
|
||||
{
|
||||
if (SDLTest_Crc32CalcStart(crcContext, crc32)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SDLTest_Crc32CalcBuffer(crcContext, inBuf, inLen, crc32)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SDLTest_Crc32CalcEnd(crcContext, crc32)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Start crc calculation */
|
||||
|
||||
int SDLTest_Crc32CalcStart(SDLTest_Crc32Context *crcContext, CrcUint32 *crc32)
|
||||
{
|
||||
/* Sanity check pointers */
|
||||
if (crcContext == NULL) {
|
||||
*crc32 = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Preload shift register, per CRC-32 spec
|
||||
*/
|
||||
*crc32 = 0xffffffff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Finish crc calculation */
|
||||
|
||||
int SDLTest_Crc32CalcEnd(SDLTest_Crc32Context *crcContext, CrcUint32 *crc32)
|
||||
{
|
||||
/* Sanity check pointers */
|
||||
if (crcContext == NULL) {
|
||||
*crc32 = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return complement, per CRC-32 spec
|
||||
*/
|
||||
*crc32 = (~(*crc32));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Include memory block in crc */
|
||||
|
||||
int SDLTest_Crc32CalcBuffer(SDLTest_Crc32Context *crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32)
|
||||
{
|
||||
CrcUint8 *p;
|
||||
register CrcUint32 crc;
|
||||
|
||||
if (crcContext == NULL) {
|
||||
*crc32 = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (inBuf == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate CRC from data
|
||||
*/
|
||||
crc = *crc32;
|
||||
for (p = inBuf; inLen > 0; ++p, --inLen) {
|
||||
#ifdef ORIGINAL_METHOD
|
||||
crc = (crc << 8) ^ crcContext->crc32_table[(crc >> 24) ^ *p];
|
||||
#else
|
||||
crc = ((crc >> 8) & 0x00FFFFFF) ^ crcContext->crc32_table[(crc ^ *p) & 0xFF];
|
||||
#endif
|
||||
}
|
||||
*crc32 = crc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SDLTest_Crc32Done(SDLTest_Crc32Context *crcContext)
|
||||
{
|
||||
if (crcContext == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
3490
external/sdl/SDL/src/test/SDL_test_font.c
vendored
Normal file
3490
external/sdl/SDL/src/test/SDL_test_font.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
488
external/sdl/SDL/src/test/SDL_test_fuzzer.c
vendored
Normal file
488
external/sdl/SDL/src/test/SDL_test_fuzzer.c
vendored
Normal file
@ -0,0 +1,488 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Data generators for fuzzing test data in a reproducible way.
|
||||
|
||||
*/
|
||||
#include <SDL3/SDL_test.h>
|
||||
|
||||
#include <float.h> /* Needed for FLT_MAX and DBL_EPSILON */
|
||||
#include <limits.h> /* Needed for UCHAR_MAX, etc. */
|
||||
|
||||
/**
|
||||
* Counter for fuzzer invocations
|
||||
*/
|
||||
static int fuzzerInvocationCounter = 0;
|
||||
|
||||
/**
|
||||
* Context for shared random number generator
|
||||
*/
|
||||
static SDLTest_RandomContext rndContext;
|
||||
|
||||
/*
|
||||
* Note: doxygen documentation markup for functions is in the header file.
|
||||
*/
|
||||
|
||||
void SDLTest_FuzzerInit(Uint64 execKey)
|
||||
{
|
||||
Uint32 a = (execKey >> 32) & 0x00000000FFFFFFFF;
|
||||
Uint32 b = execKey & 0x00000000FFFFFFFF;
|
||||
SDL_memset((void *)&rndContext, 0, sizeof(SDLTest_RandomContext));
|
||||
SDLTest_RandomInit(&rndContext, a, b);
|
||||
fuzzerInvocationCounter = 0;
|
||||
}
|
||||
|
||||
int SDLTest_GetFuzzerInvocationCount(void)
|
||||
{
|
||||
return fuzzerInvocationCounter;
|
||||
}
|
||||
|
||||
Uint8 SDLTest_RandomUint8(void)
|
||||
{
|
||||
fuzzerInvocationCounter++;
|
||||
|
||||
return (Uint8)SDLTest_RandomInt(&rndContext) & 0x000000FF;
|
||||
}
|
||||
|
||||
Sint8 SDLTest_RandomSint8(void)
|
||||
{
|
||||
fuzzerInvocationCounter++;
|
||||
|
||||
return (Sint8)SDLTest_RandomInt(&rndContext) & 0x000000FF;
|
||||
}
|
||||
|
||||
Uint16 SDLTest_RandomUint16(void)
|
||||
{
|
||||
fuzzerInvocationCounter++;
|
||||
|
||||
return (Uint16)SDLTest_RandomInt(&rndContext) & 0x0000FFFF;
|
||||
}
|
||||
|
||||
Sint16 SDLTest_RandomSint16(void)
|
||||
{
|
||||
fuzzerInvocationCounter++;
|
||||
|
||||
return (Sint16)SDLTest_RandomInt(&rndContext) & 0x0000FFFF;
|
||||
}
|
||||
|
||||
Sint32 SDLTest_RandomSint32(void)
|
||||
{
|
||||
fuzzerInvocationCounter++;
|
||||
|
||||
return (Sint32)SDLTest_RandomInt(&rndContext);
|
||||
}
|
||||
|
||||
Uint32 SDLTest_RandomUint32(void)
|
||||
{
|
||||
fuzzerInvocationCounter++;
|
||||
|
||||
return (Uint32)SDLTest_RandomInt(&rndContext);
|
||||
}
|
||||
|
||||
Uint64 SDLTest_RandomUint64(void)
|
||||
{
|
||||
union
|
||||
{
|
||||
Uint64 v64;
|
||||
Uint32 v32[2];
|
||||
} value;
|
||||
value.v64 = 0;
|
||||
|
||||
fuzzerInvocationCounter++;
|
||||
|
||||
value.v32[0] = SDLTest_RandomSint32();
|
||||
value.v32[1] = SDLTest_RandomSint32();
|
||||
|
||||
return value.v64;
|
||||
}
|
||||
|
||||
Sint64 SDLTest_RandomSint64(void)
|
||||
{
|
||||
union
|
||||
{
|
||||
Uint64 v64;
|
||||
Uint32 v32[2];
|
||||
} value;
|
||||
value.v64 = 0;
|
||||
|
||||
fuzzerInvocationCounter++;
|
||||
|
||||
value.v32[0] = SDLTest_RandomSint32();
|
||||
value.v32[1] = SDLTest_RandomSint32();
|
||||
|
||||
return (Sint64)value.v64;
|
||||
}
|
||||
|
||||
Sint32 SDLTest_RandomIntegerInRange(Sint32 pMin, Sint32 pMax)
|
||||
{
|
||||
Sint64 min = pMin;
|
||||
Sint64 max = pMax;
|
||||
Sint64 temp;
|
||||
Sint64 number;
|
||||
|
||||
if (pMin > pMax) {
|
||||
temp = min;
|
||||
min = max;
|
||||
max = temp;
|
||||
} else if (pMin == pMax) {
|
||||
return (Sint32)min;
|
||||
}
|
||||
|
||||
number = SDLTest_RandomUint32();
|
||||
/* invocation count increment in preceding call */
|
||||
|
||||
return (Sint32)((number % ((max + 1) - min)) + min);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a unsigned boundary value between the given boundaries.
|
||||
* Boundary values are inclusive. See the examples below.
|
||||
* If boundary2 < boundary1, the values are swapped.
|
||||
* If boundary1 == boundary2, value of boundary1 will be returned
|
||||
*
|
||||
* Generating boundary values for Uint8:
|
||||
* BoundaryValues(UINT8_MAX, 10, 20, True) -> [10,11,19,20]
|
||||
* BoundaryValues(UINT8_MAX, 10, 20, False) -> [9,21]
|
||||
* BoundaryValues(UINT8_MAX, 0, 15, True) -> [0, 1, 14, 15]
|
||||
* BoundaryValues(UINT8_MAX, 0, 15, False) -> [16]
|
||||
* BoundaryValues(UINT8_MAX, 0, 0xFF, False) -> [0], error set
|
||||
*
|
||||
* Generator works the same for other types of unsigned integers.
|
||||
*
|
||||
* \param maxValue The biggest value that is acceptable for this data type.
|
||||
* For instance, for Uint8 -> 255, Uint16 -> 65536 etc.
|
||||
* \param boundary1 defines lower boundary
|
||||
* \param boundary2 defines upper boundary
|
||||
* \param validDomain Generate only for valid domain (for the data type)
|
||||
*
|
||||
* \returns Returns a random boundary value for the domain or 0 in case of error
|
||||
*/
|
||||
static Uint64 SDLTest_GenerateUnsignedBoundaryValues(const Uint64 maxValue, Uint64 boundary1, Uint64 boundary2, SDL_bool validDomain)
|
||||
{
|
||||
Uint64 b1, b2;
|
||||
Uint64 delta;
|
||||
Uint64 tempBuf[4];
|
||||
Uint8 index;
|
||||
|
||||
/* Maybe swap */
|
||||
if (boundary1 > boundary2) {
|
||||
b1 = boundary2;
|
||||
b2 = boundary1;
|
||||
} else {
|
||||
b1 = boundary1;
|
||||
b2 = boundary2;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
if (validDomain == SDL_TRUE) {
|
||||
if (b1 == b2) {
|
||||
return b1;
|
||||
}
|
||||
|
||||
/* Generate up to 4 values within bounds */
|
||||
delta = b2 - b1;
|
||||
if (delta < 4) {
|
||||
do {
|
||||
tempBuf[index] = b1 + index;
|
||||
index++;
|
||||
} while (index < delta);
|
||||
} else {
|
||||
tempBuf[index] = b1;
|
||||
index++;
|
||||
tempBuf[index] = b1 + 1;
|
||||
index++;
|
||||
tempBuf[index] = b2 - 1;
|
||||
index++;
|
||||
tempBuf[index] = b2;
|
||||
index++;
|
||||
}
|
||||
} else {
|
||||
/* Generate up to 2 values outside of bounds */
|
||||
if (b1 > 0) {
|
||||
tempBuf[index] = b1 - 1;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (b2 < maxValue) {
|
||||
tempBuf[index] = b2 + 1;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == 0) {
|
||||
/* There are no valid boundaries */
|
||||
SDL_Unsupported();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return tempBuf[SDLTest_RandomUint8() % index];
|
||||
}
|
||||
|
||||
Uint8 SDLTest_RandomUint8BoundaryValue(Uint8 boundary1, Uint8 boundary2, SDL_bool validDomain)
|
||||
{
|
||||
/* max value for Uint8 */
|
||||
const Uint64 maxValue = UCHAR_MAX;
|
||||
return (Uint8)SDLTest_GenerateUnsignedBoundaryValues(maxValue,
|
||||
(Uint64)boundary1, (Uint64)boundary2,
|
||||
validDomain);
|
||||
}
|
||||
|
||||
Uint16 SDLTest_RandomUint16BoundaryValue(Uint16 boundary1, Uint16 boundary2, SDL_bool validDomain)
|
||||
{
|
||||
/* max value for Uint16 */
|
||||
const Uint64 maxValue = USHRT_MAX;
|
||||
return (Uint16)SDLTest_GenerateUnsignedBoundaryValues(maxValue,
|
||||
(Uint64)boundary1, (Uint64)boundary2,
|
||||
validDomain);
|
||||
}
|
||||
|
||||
Uint32 SDLTest_RandomUint32BoundaryValue(Uint32 boundary1, Uint32 boundary2, SDL_bool validDomain)
|
||||
{
|
||||
/* max value for Uint32 */
|
||||
#if ((ULONG_MAX) == (UINT_MAX))
|
||||
const Uint64 maxValue = ULONG_MAX;
|
||||
#else
|
||||
const Uint64 maxValue = UINT_MAX;
|
||||
#endif
|
||||
return (Uint32)SDLTest_GenerateUnsignedBoundaryValues(maxValue,
|
||||
(Uint64)boundary1, (Uint64)boundary2,
|
||||
validDomain);
|
||||
}
|
||||
|
||||
Uint64 SDLTest_RandomUint64BoundaryValue(Uint64 boundary1, Uint64 boundary2, SDL_bool validDomain)
|
||||
{
|
||||
/* max value for Uint64 */
|
||||
const Uint64 maxValue = UINT64_MAX;
|
||||
return SDLTest_GenerateUnsignedBoundaryValues(maxValue,
|
||||
boundary1, boundary2,
|
||||
validDomain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a signed boundary value between the given boundaries.
|
||||
* Boundary values are inclusive. See the examples below.
|
||||
* If boundary2 < boundary1, the values are swapped.
|
||||
* If boundary1 == boundary2, value of boundary1 will be returned
|
||||
*
|
||||
* Generating boundary values for Sint8:
|
||||
* SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -10, 20, True) -> [-10,-9,19,20]
|
||||
* SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -10, 20, False) -> [-11,21]
|
||||
* SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -30, -15, True) -> [-30, -29, -16, -15]
|
||||
* SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -127, 15, False) -> [16]
|
||||
* SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -127, 127, False) -> [0], error set
|
||||
*
|
||||
* Generator works the same for other types of signed integers.
|
||||
*
|
||||
* \param minValue The smallest value that is acceptable for this data type.
|
||||
* For instance, for Uint8 -> -127, etc.
|
||||
* \param maxValue The biggest value that is acceptable for this data type.
|
||||
* For instance, for Uint8 -> 127, etc.
|
||||
* \param boundary1 defines lower boundary
|
||||
* \param boundary2 defines upper boundary
|
||||
* \param validDomain Generate only for valid domain (for the data type)
|
||||
*
|
||||
* \returns Returns a random boundary value for the domain or 0 in case of error
|
||||
*/
|
||||
static Sint64 SDLTest_GenerateSignedBoundaryValues(const Sint64 minValue, const Sint64 maxValue, Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain)
|
||||
{
|
||||
Sint64 b1, b2;
|
||||
Sint64 delta;
|
||||
Sint64 tempBuf[4];
|
||||
Uint8 index;
|
||||
|
||||
/* Maybe swap */
|
||||
if (boundary1 > boundary2) {
|
||||
b1 = boundary2;
|
||||
b2 = boundary1;
|
||||
} else {
|
||||
b1 = boundary1;
|
||||
b2 = boundary2;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
if (validDomain == SDL_TRUE) {
|
||||
if (b1 == b2) {
|
||||
return b1;
|
||||
}
|
||||
|
||||
/* Generate up to 4 values within bounds */
|
||||
delta = b2 - b1;
|
||||
if (delta < 4) {
|
||||
do {
|
||||
tempBuf[index] = b1 + index;
|
||||
index++;
|
||||
} while (index < delta);
|
||||
} else {
|
||||
tempBuf[index] = b1;
|
||||
index++;
|
||||
tempBuf[index] = b1 + 1;
|
||||
index++;
|
||||
tempBuf[index] = b2 - 1;
|
||||
index++;
|
||||
tempBuf[index] = b2;
|
||||
index++;
|
||||
}
|
||||
} else {
|
||||
/* Generate up to 2 values outside of bounds */
|
||||
if (b1 > minValue) {
|
||||
tempBuf[index] = b1 - 1;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (b2 < maxValue) {
|
||||
tempBuf[index] = b2 + 1;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == 0) {
|
||||
/* There are no valid boundaries */
|
||||
SDL_Unsupported();
|
||||
return minValue;
|
||||
}
|
||||
|
||||
return tempBuf[SDLTest_RandomUint8() % index];
|
||||
}
|
||||
|
||||
Sint8 SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, SDL_bool validDomain)
|
||||
{
|
||||
/* min & max values for Sint8 */
|
||||
const Sint64 maxValue = SCHAR_MAX;
|
||||
const Sint64 minValue = SCHAR_MIN;
|
||||
return (Sint8)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
|
||||
(Sint64)boundary1, (Sint64)boundary2,
|
||||
validDomain);
|
||||
}
|
||||
|
||||
Sint16 SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, SDL_bool validDomain)
|
||||
{
|
||||
/* min & max values for Sint16 */
|
||||
const Sint64 maxValue = SHRT_MAX;
|
||||
const Sint64 minValue = SHRT_MIN;
|
||||
return (Sint16)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
|
||||
(Sint64)boundary1, (Sint64)boundary2,
|
||||
validDomain);
|
||||
}
|
||||
|
||||
Sint32 SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, SDL_bool validDomain)
|
||||
{
|
||||
/* min & max values for Sint32 */
|
||||
#if ((ULONG_MAX) == (UINT_MAX))
|
||||
const Sint64 maxValue = LONG_MAX;
|
||||
const Sint64 minValue = LONG_MIN;
|
||||
#else
|
||||
const Sint64 maxValue = INT_MAX;
|
||||
const Sint64 minValue = INT_MIN;
|
||||
#endif
|
||||
return (Sint32)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
|
||||
(Sint64)boundary1, (Sint64)boundary2,
|
||||
validDomain);
|
||||
}
|
||||
|
||||
Sint64 SDLTest_RandomSint64BoundaryValue(Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain)
|
||||
{
|
||||
/* min & max values for Sint64 */
|
||||
const Sint64 maxValue = INT64_MAX;
|
||||
const Sint64 minValue = INT64_MIN;
|
||||
return SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
|
||||
boundary1, boundary2,
|
||||
validDomain);
|
||||
}
|
||||
|
||||
float SDLTest_RandomUnitFloat(void)
|
||||
{
|
||||
return SDLTest_RandomUint32() / (float)UINT_MAX;
|
||||
}
|
||||
|
||||
float SDLTest_RandomFloat(void)
|
||||
{
|
||||
return (float)(SDLTest_RandomUnitDouble() * 2.0 * (double)FLT_MAX - (double)(FLT_MAX));
|
||||
}
|
||||
|
||||
double
|
||||
SDLTest_RandomUnitDouble(void)
|
||||
{
|
||||
return (double)(SDLTest_RandomUint64() >> 11) * (1.0 / 9007199254740992.0);
|
||||
}
|
||||
|
||||
double
|
||||
SDLTest_RandomDouble(void)
|
||||
{
|
||||
double r = 0.0;
|
||||
double s = 1.0;
|
||||
do {
|
||||
s /= UINT_MAX + 1.0;
|
||||
r += (double)SDLTest_RandomInt(&rndContext) * s;
|
||||
} while (s > DBL_EPSILON);
|
||||
|
||||
fuzzerInvocationCounter++;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
char *SDLTest_RandomAsciiString(void)
|
||||
{
|
||||
return SDLTest_RandomAsciiStringWithMaximumLength(255);
|
||||
}
|
||||
|
||||
char *SDLTest_RandomAsciiStringWithMaximumLength(int maxLength)
|
||||
{
|
||||
int size;
|
||||
|
||||
if (maxLength < 1) {
|
||||
SDL_InvalidParamError("maxLength");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size = (SDLTest_RandomUint32() % (maxLength + 1));
|
||||
if (size == 0) {
|
||||
size = 1;
|
||||
}
|
||||
return SDLTest_RandomAsciiStringOfSize(size);
|
||||
}
|
||||
|
||||
char *SDLTest_RandomAsciiStringOfSize(int size)
|
||||
{
|
||||
char *string;
|
||||
int counter;
|
||||
|
||||
if (size < 1) {
|
||||
SDL_InvalidParamError("size");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
string = (char *)SDL_malloc((size + 1) * sizeof(char));
|
||||
if (string == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (counter = 0; counter < size; ++counter) {
|
||||
string[counter] = (char)SDLTest_RandomIntegerInRange(32, 126);
|
||||
}
|
||||
|
||||
string[counter] = '\0';
|
||||
|
||||
fuzzerInvocationCounter++;
|
||||
|
||||
return string;
|
||||
}
|
698
external/sdl/SDL/src/test/SDL_test_harness.c
vendored
Normal file
698
external/sdl/SDL/src/test/SDL_test_harness.c
vendored
Normal file
@ -0,0 +1,698 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include <SDL3/SDL_test.h>
|
||||
|
||||
#include <stdlib.h> /* Needed for exit() */
|
||||
|
||||
/* Enable to have color in logs */
|
||||
#if 1
|
||||
#define COLOR_RED "\033[0;31m"
|
||||
#define COLOR_GREEN "\033[0;32m"
|
||||
#define COLOR_YELLOW "\033[0;93m"
|
||||
#define COLOR_BLUE "\033[0;94m"
|
||||
#define COLOR_END "\033[0m"
|
||||
#else
|
||||
#define COLOR_RED ""
|
||||
#define COLOR_GREEN ""
|
||||
#define COLOR_BLUE ""
|
||||
#define COLOR_YELLOW ""
|
||||
#define COLOR_END ""
|
||||
#endif
|
||||
|
||||
/* Invalid test name/description message format */
|
||||
#define SDLTEST_INVALID_NAME_FORMAT "(Invalid)"
|
||||
|
||||
/* Log summary message format */
|
||||
#define SDLTEST_LOG_SUMMARY_FORMAT "%s Summary: Total=%d " COLOR_GREEN "Passed=%d" COLOR_END " " COLOR_RED "Failed=%d" COLOR_END " " COLOR_BLUE "Skipped=%d" COLOR_END
|
||||
#define SDLTEST_LOG_SUMMARY_FORMAT_OK "%s Summary: Total=%d " COLOR_GREEN "Passed=%d" COLOR_END " " COLOR_GREEN "Failed=%d" COLOR_END " " COLOR_BLUE "Skipped=%d" COLOR_END
|
||||
|
||||
/* Final result message format */
|
||||
#define SDLTEST_FINAL_RESULT_FORMAT COLOR_YELLOW ">>> %s '%s':" COLOR_END " %s\n"
|
||||
|
||||
/* ! \brief Timeout for single test case execution */
|
||||
static Uint32 SDLTest_TestCaseTimeout = 3600;
|
||||
|
||||
/**
|
||||
* Generates a random run seed string for the harness. The generated seed
|
||||
* will contain alphanumeric characters (0-9A-Z).
|
||||
*
|
||||
* Note: The returned string needs to be deallocated by the caller.
|
||||
*
|
||||
* \param length The length of the seed string to generate
|
||||
*
|
||||
* \returns The generated seed string
|
||||
*/
|
||||
char *SDLTest_GenerateRunSeed(const int length)
|
||||
{
|
||||
char *seed = NULL;
|
||||
SDLTest_RandomContext randomContext;
|
||||
int counter;
|
||||
|
||||
/* Sanity check input */
|
||||
if (length <= 0) {
|
||||
SDLTest_LogError("The length of the harness seed must be >0.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate output buffer */
|
||||
seed = (char *)SDL_malloc((length + 1) * sizeof(char));
|
||||
if (seed == NULL) {
|
||||
SDLTest_LogError("SDL_malloc for run seed output buffer failed.");
|
||||
SDL_Error(SDL_ENOMEM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Generate a random string of alphanumeric characters */
|
||||
SDLTest_RandomInitTime(&randomContext);
|
||||
for (counter = 0; counter < length; counter++) {
|
||||
unsigned int number = SDLTest_Random(&randomContext);
|
||||
char ch = (char)(number % (91 - 48)) + 48;
|
||||
if (ch >= 58 && ch <= 64) {
|
||||
ch = 65;
|
||||
}
|
||||
seed[counter] = ch;
|
||||
}
|
||||
seed[length] = '\0';
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an execution key for the fuzzer.
|
||||
*
|
||||
* \param runSeed The run seed to use
|
||||
* \param suiteName The name of the test suite
|
||||
* \param testName The name of the test
|
||||
* \param iteration The iteration count
|
||||
*
|
||||
* \returns The generated execution key to initialize the fuzzer with.
|
||||
*
|
||||
*/
|
||||
static Uint64 SDLTest_GenerateExecKey(const char *runSeed, const char *suiteName, const char *testName, int iteration)
|
||||
{
|
||||
SDLTest_Md5Context md5Context;
|
||||
Uint64 *keys;
|
||||
char iterationString[16];
|
||||
size_t runSeedLength;
|
||||
size_t suiteNameLength;
|
||||
size_t testNameLength;
|
||||
size_t iterationStringLength;
|
||||
size_t entireStringLength;
|
||||
char *buffer;
|
||||
|
||||
if (runSeed == NULL || runSeed[0] == '\0') {
|
||||
SDLTest_LogError("Invalid runSeed string.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (suiteName == NULL || suiteName[0] == '\0') {
|
||||
SDLTest_LogError("Invalid suiteName string.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (testName == NULL || testName[0] == '\0') {
|
||||
SDLTest_LogError("Invalid testName string.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (iteration <= 0) {
|
||||
SDLTest_LogError("Invalid iteration count.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Convert iteration number into a string */
|
||||
SDL_memset(iterationString, 0, sizeof(iterationString));
|
||||
(void)SDL_snprintf(iterationString, sizeof(iterationString) - 1, "%d", iteration);
|
||||
|
||||
/* Combine the parameters into single string */
|
||||
runSeedLength = SDL_strlen(runSeed);
|
||||
suiteNameLength = SDL_strlen(suiteName);
|
||||
testNameLength = SDL_strlen(testName);
|
||||
iterationStringLength = SDL_strlen(iterationString);
|
||||
entireStringLength = runSeedLength + suiteNameLength + testNameLength + iterationStringLength + 1;
|
||||
buffer = (char *)SDL_malloc(entireStringLength);
|
||||
if (buffer == NULL) {
|
||||
SDLTest_LogError("Failed to allocate buffer for execKey generation.");
|
||||
SDL_Error(SDL_ENOMEM);
|
||||
return 0;
|
||||
}
|
||||
(void)SDL_snprintf(buffer, entireStringLength, "%s%s%s%d", runSeed, suiteName, testName, iteration);
|
||||
|
||||
/* Hash string and use half of the digest as 64bit exec key */
|
||||
SDLTest_Md5Init(&md5Context);
|
||||
SDLTest_Md5Update(&md5Context, (unsigned char *)buffer, (unsigned int)entireStringLength);
|
||||
SDLTest_Md5Final(&md5Context);
|
||||
SDL_free(buffer);
|
||||
keys = (Uint64 *)md5Context.digest;
|
||||
|
||||
return keys[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set timeout handler for test.
|
||||
*
|
||||
* Note: SDL_Init(SDL_INIT_TIMER) will be called if it wasn't done so before.
|
||||
*
|
||||
* \param timeout Timeout interval in seconds.
|
||||
* \param callback Function that will be called after timeout has elapsed.
|
||||
*
|
||||
* \return Timer id or -1 on failure.
|
||||
*/
|
||||
static SDL_TimerID SDLTest_SetTestTimeout(int timeout, void(SDLCALL *callback)(void))
|
||||
{
|
||||
Uint32 timeoutInMilliseconds;
|
||||
SDL_TimerID timerID;
|
||||
|
||||
if (callback == NULL) {
|
||||
SDLTest_LogError("Timeout callback can't be NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (timeout < 0) {
|
||||
SDLTest_LogError("Timeout value must be bigger than zero.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Init SDL timer if not initialized before */
|
||||
if (SDL_WasInit(SDL_INIT_TIMER) == 0) {
|
||||
if (SDL_InitSubSystem(SDL_INIT_TIMER)) {
|
||||
SDLTest_LogError("Failed to init timer subsystem: %s", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set timer */
|
||||
timeoutInMilliseconds = timeout * 1000;
|
||||
timerID = SDL_AddTimer(timeoutInMilliseconds, (SDL_TimerCallback)callback, 0x0);
|
||||
if (timerID == 0) {
|
||||
SDLTest_LogError("Creation of SDL timer failed: %s", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return timerID;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Timeout handler. Aborts test run and exits harness process.
|
||||
*/
|
||||
#ifdef __WATCOMC__
|
||||
#pragma aux SDLTest_BailOut aborts;
|
||||
#endif
|
||||
static SDL_NORETURN void SDLCALL SDLTest_BailOut(void)
|
||||
{
|
||||
SDLTest_LogError("TestCaseTimeout timer expired. Aborting test run.");
|
||||
exit(TEST_ABORTED); /* bail out from the test */
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Execute a test using the given execution key.
|
||||
*
|
||||
* \param testSuite Suite containing the test case.
|
||||
* \param testCase Case to execute.
|
||||
* \param execKey Execution key for the fuzzer.
|
||||
* \param forceTestRun Force test to run even if test was disabled in suite.
|
||||
*
|
||||
* \returns Test case result.
|
||||
*/
|
||||
static int SDLTest_RunTest(SDLTest_TestSuiteReference *testSuite, const SDLTest_TestCaseReference *testCase, Uint64 execKey, SDL_bool forceTestRun)
|
||||
{
|
||||
SDL_TimerID timer = 0;
|
||||
int testCaseResult = 0;
|
||||
int testResult = 0;
|
||||
int fuzzerCount;
|
||||
|
||||
if (testSuite == NULL || testCase == NULL || testSuite->name == NULL || testCase->name == NULL) {
|
||||
SDLTest_LogError("Setup failure: testSuite or testCase references NULL");
|
||||
return TEST_RESULT_SETUP_FAILURE;
|
||||
}
|
||||
|
||||
if (!testCase->enabled && forceTestRun == SDL_FALSE) {
|
||||
SDLTest_Log(SDLTEST_FINAL_RESULT_FORMAT, "Test", testCase->name, "Skipped (Disabled)");
|
||||
return TEST_RESULT_SKIPPED;
|
||||
}
|
||||
|
||||
/* Initialize fuzzer */
|
||||
SDLTest_FuzzerInit(execKey);
|
||||
|
||||
/* Reset assert tracker */
|
||||
SDLTest_ResetAssertSummary();
|
||||
|
||||
/* Set timeout timer */
|
||||
timer = SDLTest_SetTestTimeout(SDLTest_TestCaseTimeout, SDLTest_BailOut);
|
||||
|
||||
/* Maybe run suite initializer function */
|
||||
if (testSuite->testSetUp) {
|
||||
testSuite->testSetUp(0x0);
|
||||
if (SDLTest_AssertSummaryToTestResult() == TEST_RESULT_FAILED) {
|
||||
SDLTest_LogError(SDLTEST_FINAL_RESULT_FORMAT, "Suite Setup", testSuite->name, COLOR_RED "Failed" COLOR_END);
|
||||
return TEST_RESULT_SETUP_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Run test case function */
|
||||
testCaseResult = testCase->testCase(0x0);
|
||||
|
||||
/* Convert test execution result into harness result */
|
||||
if (testCaseResult == TEST_SKIPPED) {
|
||||
/* Test was programmatically skipped */
|
||||
testResult = TEST_RESULT_SKIPPED;
|
||||
} else if (testCaseResult == TEST_STARTED) {
|
||||
/* Test did not return a TEST_COMPLETED value; assume it failed */
|
||||
testResult = TEST_RESULT_FAILED;
|
||||
} else if (testCaseResult == TEST_ABORTED) {
|
||||
/* Test was aborted early; assume it failed */
|
||||
testResult = TEST_RESULT_FAILED;
|
||||
} else {
|
||||
/* Perform failure analysis based on asserts */
|
||||
testResult = SDLTest_AssertSummaryToTestResult();
|
||||
}
|
||||
|
||||
/* Maybe run suite cleanup function (ignore failed asserts) */
|
||||
if (testSuite->testTearDown) {
|
||||
testSuite->testTearDown(0x0);
|
||||
}
|
||||
|
||||
/* Cancel timeout timer */
|
||||
if (timer) {
|
||||
SDL_RemoveTimer(timer);
|
||||
}
|
||||
|
||||
/* Report on asserts and fuzzer usage */
|
||||
fuzzerCount = SDLTest_GetFuzzerInvocationCount();
|
||||
if (fuzzerCount > 0) {
|
||||
SDLTest_Log("Fuzzer invocations: %d", fuzzerCount);
|
||||
}
|
||||
|
||||
/* Final log based on test execution result */
|
||||
if (testCaseResult == TEST_SKIPPED) {
|
||||
/* Test was programmatically skipped */
|
||||
SDLTest_Log(SDLTEST_FINAL_RESULT_FORMAT, "Test", testCase->name, COLOR_BLUE "Skipped (Programmatically)" COLOR_END);
|
||||
} else if (testCaseResult == TEST_STARTED) {
|
||||
/* Test did not return a TEST_COMPLETED value; assume it failed */
|
||||
SDLTest_LogError(SDLTEST_FINAL_RESULT_FORMAT, "Test", testCase->name, COLOR_RED "Failed (test started, but did not return TEST_COMPLETED)" COLOR_END);
|
||||
} else if (testCaseResult == TEST_ABORTED) {
|
||||
/* Test was aborted early; assume it failed */
|
||||
SDLTest_LogError(SDLTEST_FINAL_RESULT_FORMAT, "Test", testCase->name, COLOR_RED "Failed (Aborted)" COLOR_END);
|
||||
} else {
|
||||
SDLTest_LogAssertSummary();
|
||||
}
|
||||
|
||||
return testResult;
|
||||
}
|
||||
|
||||
/* Prints summary of all suites/tests contained in the given reference */
|
||||
#if 0
|
||||
static void SDLTest_LogTestSuiteSummary(SDLTest_TestSuiteReference *testSuites)
|
||||
{
|
||||
int suiteCounter;
|
||||
int testCounter;
|
||||
SDLTest_TestSuiteReference *testSuite;
|
||||
SDLTest_TestCaseReference *testCase;
|
||||
|
||||
/* Loop over all suites */
|
||||
suiteCounter = 0;
|
||||
while (&testSuites[suiteCounter]) {
|
||||
testSuite=&testSuites[suiteCounter];
|
||||
suiteCounter++;
|
||||
SDLTest_Log("Test Suite %i - %s\n", suiteCounter,
|
||||
(testSuite->name) ? testSuite->name : SDLTEST_INVALID_NAME_FORMAT);
|
||||
|
||||
/* Loop over all test cases */
|
||||
testCounter = 0;
|
||||
while (testSuite->testCases[testCounter]) {
|
||||
testCase=(SDLTest_TestCaseReference *)testSuite->testCases[testCounter];
|
||||
testCounter++;
|
||||
SDLTest_Log(" Test Case %i - %s: %s", testCounter,
|
||||
(testCase->name) ? testCase->name : SDLTEST_INVALID_NAME_FORMAT,
|
||||
(testCase->description) ? testCase->description : SDLTEST_INVALID_NAME_FORMAT);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Gets a timer value in seconds */
|
||||
static float GetClock(void)
|
||||
{
|
||||
float currentClock = SDL_GetPerformanceCounter() / (float)SDL_GetPerformanceFrequency();
|
||||
return currentClock;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Execute a test suite using the given run seed and execution key.
|
||||
*
|
||||
* The filter string is matched to the suite name (full comparison) to select a single suite,
|
||||
* or if no suite matches, it is matched to the test names (full comparison) to select a single test.
|
||||
*
|
||||
* \param testSuites Suites containing the test case.
|
||||
* \param userRunSeed Custom run seed provided by user, or NULL to autogenerate one.
|
||||
* \param userExecKey Custom execution key provided by user, or 0 to autogenerate one.
|
||||
* \param filter Filter specification. NULL disables. Case sensitive.
|
||||
* \param testIterations Number of iterations to run each test case.
|
||||
*
|
||||
* \returns Test run result; 0 when all tests passed, 1 if any tests failed.
|
||||
*/
|
||||
int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *userRunSeed, Uint64 userExecKey, const char *filter, int testIterations)
|
||||
{
|
||||
int totalNumberOfTests = 0;
|
||||
int failedNumberOfTests = 0;
|
||||
int suiteCounter;
|
||||
int testCounter;
|
||||
int iterationCounter;
|
||||
SDLTest_TestSuiteReference *testSuite;
|
||||
const SDLTest_TestCaseReference *testCase;
|
||||
const char *runSeed = NULL;
|
||||
const char *currentSuiteName;
|
||||
const char *currentTestName;
|
||||
Uint64 execKey;
|
||||
float runStartSeconds;
|
||||
float suiteStartSeconds;
|
||||
float testStartSeconds;
|
||||
float runEndSeconds;
|
||||
float suiteEndSeconds;
|
||||
float testEndSeconds;
|
||||
float runtime;
|
||||
int suiteFilter = 0;
|
||||
const char *suiteFilterName = NULL;
|
||||
int testFilter = 0;
|
||||
const char *testFilterName = NULL;
|
||||
SDL_bool forceTestRun = SDL_FALSE;
|
||||
int testResult = 0;
|
||||
int runResult = 0;
|
||||
int totalTestFailedCount = 0;
|
||||
int totalTestPassedCount = 0;
|
||||
int totalTestSkippedCount = 0;
|
||||
int testFailedCount = 0;
|
||||
int testPassedCount = 0;
|
||||
int testSkippedCount = 0;
|
||||
int countSum = 0;
|
||||
const SDLTest_TestCaseReference **failedTests;
|
||||
char generatedSeed[16 + 1];
|
||||
|
||||
/* Sanitize test iterations */
|
||||
if (testIterations < 1) {
|
||||
testIterations = 1;
|
||||
}
|
||||
|
||||
/* Generate run see if we don't have one already */
|
||||
if (userRunSeed == NULL || userRunSeed[0] == '\0') {
|
||||
char *tmp = SDLTest_GenerateRunSeed(16);
|
||||
if (tmp == NULL) {
|
||||
SDLTest_LogError("Generating a random seed failed");
|
||||
return 2;
|
||||
}
|
||||
SDL_memcpy(generatedSeed, tmp, 16 + 1);
|
||||
SDL_free(tmp);
|
||||
runSeed = generatedSeed;
|
||||
} else {
|
||||
runSeed = userRunSeed;
|
||||
}
|
||||
|
||||
/* Reset per-run counters */
|
||||
totalTestFailedCount = 0;
|
||||
totalTestPassedCount = 0;
|
||||
totalTestSkippedCount = 0;
|
||||
|
||||
/* Take time - run start */
|
||||
runStartSeconds = GetClock();
|
||||
|
||||
/* Log run with fuzzer parameters */
|
||||
SDLTest_Log("::::: Test Run /w seed '%s' started\n", runSeed);
|
||||
|
||||
/* Count the total number of tests */
|
||||
suiteCounter = 0;
|
||||
while (testSuites[suiteCounter]) {
|
||||
testSuite = testSuites[suiteCounter];
|
||||
suiteCounter++;
|
||||
testCounter = 0;
|
||||
while (testSuite->testCases[testCounter]) {
|
||||
testCounter++;
|
||||
totalNumberOfTests++;
|
||||
}
|
||||
}
|
||||
|
||||
if (totalNumberOfTests == 0) {
|
||||
SDLTest_LogError("No tests to run?");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Pre-allocate an array for tracking failed tests (potentially all test cases) */
|
||||
failedTests = (const SDLTest_TestCaseReference **)SDL_malloc(totalNumberOfTests * sizeof(SDLTest_TestCaseReference *));
|
||||
if (failedTests == NULL) {
|
||||
SDLTest_LogError("Unable to allocate cache for failed tests");
|
||||
SDL_Error(SDL_ENOMEM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize filtering */
|
||||
if (filter != NULL && filter[0] != '\0') {
|
||||
/* Loop over all suites to check if we have a filter match */
|
||||
suiteCounter = 0;
|
||||
while (testSuites[suiteCounter] && suiteFilter == 0) {
|
||||
testSuite = testSuites[suiteCounter];
|
||||
suiteCounter++;
|
||||
if (testSuite->name != NULL && SDL_strcasecmp(filter, testSuite->name) == 0) {
|
||||
/* Matched a suite name */
|
||||
suiteFilter = 1;
|
||||
suiteFilterName = testSuite->name;
|
||||
SDLTest_Log("Filtering: running only suite '%s'", suiteFilterName);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Within each suite, loop over all test cases to check if we have a filter match */
|
||||
testCounter = 0;
|
||||
while (testSuite->testCases[testCounter] && testFilter == 0) {
|
||||
testCase = testSuite->testCases[testCounter];
|
||||
testCounter++;
|
||||
if (testCase->name != NULL && SDL_strcasecmp(filter, testCase->name) == 0) {
|
||||
/* Matched a test name */
|
||||
suiteFilter = 1;
|
||||
suiteFilterName = testSuite->name;
|
||||
testFilter = 1;
|
||||
testFilterName = testCase->name;
|
||||
SDLTest_Log("Filtering: running only test '%s' in suite '%s'", testFilterName, suiteFilterName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (suiteFilter == 0 && testFilter == 0) {
|
||||
SDLTest_LogError("Filter '%s' did not match any test suite/case.", filter);
|
||||
for (suiteCounter = 0; testSuites[suiteCounter]; ++suiteCounter) {
|
||||
testSuite = testSuites[suiteCounter];
|
||||
if (testSuite->name != NULL) {
|
||||
SDLTest_Log("Test suite: %s", testSuite->name);
|
||||
}
|
||||
|
||||
/* Within each suite, loop over all test cases to check if we have a filter match */
|
||||
for (testCounter = 0; testSuite->testCases[testCounter]; ++testCounter) {
|
||||
testCase = testSuite->testCases[testCounter];
|
||||
SDLTest_Log(" test: %s", testCase->name);
|
||||
}
|
||||
}
|
||||
SDLTest_Log("Exit code: 2");
|
||||
SDL_free((void *)failedTests);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop over all suites */
|
||||
suiteCounter = 0;
|
||||
while (testSuites[suiteCounter]) {
|
||||
testSuite = testSuites[suiteCounter];
|
||||
currentSuiteName = (testSuite->name ? testSuite->name : SDLTEST_INVALID_NAME_FORMAT);
|
||||
suiteCounter++;
|
||||
|
||||
/* Filter suite if flag set and we have a name */
|
||||
if (suiteFilter == 1 && suiteFilterName != NULL && testSuite->name != NULL &&
|
||||
SDL_strcasecmp(suiteFilterName, testSuite->name) != 0) {
|
||||
/* Skip suite */
|
||||
SDLTest_Log("===== Test Suite %i: '%s' " COLOR_BLUE "skipped" COLOR_END "\n",
|
||||
suiteCounter,
|
||||
currentSuiteName);
|
||||
} else {
|
||||
|
||||
/* Reset per-suite counters */
|
||||
testFailedCount = 0;
|
||||
testPassedCount = 0;
|
||||
testSkippedCount = 0;
|
||||
|
||||
/* Take time - suite start */
|
||||
suiteStartSeconds = GetClock();
|
||||
|
||||
/* Log suite started */
|
||||
SDLTest_Log("===== Test Suite %i: '%s' started\n",
|
||||
suiteCounter,
|
||||
currentSuiteName);
|
||||
|
||||
/* Loop over all test cases */
|
||||
testCounter = 0;
|
||||
while (testSuite->testCases[testCounter]) {
|
||||
testCase = testSuite->testCases[testCounter];
|
||||
currentTestName = (testCase->name ? testCase->name : SDLTEST_INVALID_NAME_FORMAT);
|
||||
testCounter++;
|
||||
|
||||
/* Filter tests if flag set and we have a name */
|
||||
if (testFilter == 1 && testFilterName != NULL && testCase->name != NULL &&
|
||||
SDL_strcasecmp(testFilterName, testCase->name) != 0) {
|
||||
/* Skip test */
|
||||
SDLTest_Log("===== Test Case %i.%i: '%s' " COLOR_BLUE "skipped" COLOR_END "\n",
|
||||
suiteCounter,
|
||||
testCounter,
|
||||
currentTestName);
|
||||
} else {
|
||||
/* Override 'disabled' flag if we specified a test filter (i.e. force run for debugging) */
|
||||
if (testFilter == 1 && !testCase->enabled) {
|
||||
SDLTest_Log("Force run of disabled test since test filter was set");
|
||||
forceTestRun = SDL_TRUE;
|
||||
}
|
||||
|
||||
/* Take time - test start */
|
||||
testStartSeconds = GetClock();
|
||||
|
||||
/* Log test started */
|
||||
SDLTest_Log(COLOR_YELLOW "----- Test Case %i.%i: '%s' started" COLOR_END,
|
||||
suiteCounter,
|
||||
testCounter,
|
||||
currentTestName);
|
||||
if (testCase->description != NULL && testCase->description[0] != '\0') {
|
||||
SDLTest_Log("Test Description: '%s'",
|
||||
(testCase->description) ? testCase->description : SDLTEST_INVALID_NAME_FORMAT);
|
||||
}
|
||||
|
||||
/* Loop over all iterations */
|
||||
iterationCounter = 0;
|
||||
while (iterationCounter < testIterations) {
|
||||
iterationCounter++;
|
||||
|
||||
if (userExecKey != 0) {
|
||||
execKey = userExecKey;
|
||||
} else {
|
||||
execKey = SDLTest_GenerateExecKey(runSeed, testSuite->name, testCase->name, iterationCounter);
|
||||
}
|
||||
|
||||
SDLTest_Log("Test Iteration %i: execKey %" SDL_PRIu64, iterationCounter, execKey);
|
||||
testResult = SDLTest_RunTest(testSuite, testCase, execKey, forceTestRun);
|
||||
|
||||
if (testResult == TEST_RESULT_PASSED) {
|
||||
testPassedCount++;
|
||||
totalTestPassedCount++;
|
||||
} else if (testResult == TEST_RESULT_SKIPPED) {
|
||||
testSkippedCount++;
|
||||
totalTestSkippedCount++;
|
||||
} else {
|
||||
testFailedCount++;
|
||||
totalTestFailedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Take time - test end */
|
||||
testEndSeconds = GetClock();
|
||||
runtime = testEndSeconds - testStartSeconds;
|
||||
if (runtime < 0.0f) {
|
||||
runtime = 0.0f;
|
||||
}
|
||||
|
||||
if (testIterations > 1) {
|
||||
/* Log test runtime */
|
||||
SDLTest_Log("Runtime of %i iterations: %.1f sec", testIterations, runtime);
|
||||
SDLTest_Log("Average Test runtime: %.5f sec", runtime / (float)testIterations);
|
||||
} else {
|
||||
/* Log test runtime */
|
||||
SDLTest_Log("Total Test runtime: %.1f sec", runtime);
|
||||
}
|
||||
|
||||
/* Log final test result */
|
||||
switch (testResult) {
|
||||
case TEST_RESULT_PASSED:
|
||||
SDLTest_Log(SDLTEST_FINAL_RESULT_FORMAT, "Test", currentTestName, COLOR_GREEN "Passed" COLOR_END);
|
||||
break;
|
||||
case TEST_RESULT_FAILED:
|
||||
SDLTest_LogError(SDLTEST_FINAL_RESULT_FORMAT, "Test", currentTestName, COLOR_RED "Failed" COLOR_END);
|
||||
break;
|
||||
case TEST_RESULT_NO_ASSERT:
|
||||
SDLTest_LogError(SDLTEST_FINAL_RESULT_FORMAT, "Test", currentTestName, COLOR_BLUE "No Asserts" COLOR_END);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Collect failed test case references for repro-step display */
|
||||
if (testResult == TEST_RESULT_FAILED) {
|
||||
failedTests[failedNumberOfTests] = testCase;
|
||||
failedNumberOfTests++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Take time - suite end */
|
||||
suiteEndSeconds = GetClock();
|
||||
runtime = suiteEndSeconds - suiteStartSeconds;
|
||||
if (runtime < 0.0f) {
|
||||
runtime = 0.0f;
|
||||
}
|
||||
|
||||
/* Log suite runtime */
|
||||
SDLTest_Log("Total Suite runtime: %.1f sec", runtime);
|
||||
|
||||
/* Log summary and final Suite result */
|
||||
countSum = testPassedCount + testFailedCount + testSkippedCount;
|
||||
if (testFailedCount == 0) {
|
||||
SDLTest_Log(SDLTEST_LOG_SUMMARY_FORMAT_OK, "Suite", countSum, testPassedCount, testFailedCount, testSkippedCount);
|
||||
SDLTest_Log(SDLTEST_FINAL_RESULT_FORMAT, "Suite", currentSuiteName, COLOR_GREEN "Passed" COLOR_END);
|
||||
} else {
|
||||
SDLTest_LogError(SDLTEST_LOG_SUMMARY_FORMAT, "Suite", countSum, testPassedCount, testFailedCount, testSkippedCount);
|
||||
SDLTest_LogError(SDLTEST_FINAL_RESULT_FORMAT, "Suite", currentSuiteName, COLOR_RED "Failed" COLOR_END);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Take time - run end */
|
||||
runEndSeconds = GetClock();
|
||||
runtime = runEndSeconds - runStartSeconds;
|
||||
if (runtime < 0.0f) {
|
||||
runtime = 0.0f;
|
||||
}
|
||||
|
||||
/* Log total runtime */
|
||||
SDLTest_Log("Total Run runtime: %.1f sec", runtime);
|
||||
|
||||
/* Log summary and final run result */
|
||||
countSum = totalTestPassedCount + totalTestFailedCount + totalTestSkippedCount;
|
||||
if (totalTestFailedCount == 0) {
|
||||
runResult = 0;
|
||||
SDLTest_Log(SDLTEST_LOG_SUMMARY_FORMAT_OK, "Run", countSum, totalTestPassedCount, totalTestFailedCount, totalTestSkippedCount);
|
||||
SDLTest_Log(SDLTEST_FINAL_RESULT_FORMAT, "Run /w seed", runSeed, COLOR_GREEN "Passed" COLOR_END);
|
||||
} else {
|
||||
runResult = 1;
|
||||
SDLTest_LogError(SDLTEST_LOG_SUMMARY_FORMAT, "Run", countSum, totalTestPassedCount, totalTestFailedCount, totalTestSkippedCount);
|
||||
SDLTest_LogError(SDLTEST_FINAL_RESULT_FORMAT, "Run /w seed", runSeed, COLOR_RED "Failed" COLOR_END);
|
||||
}
|
||||
|
||||
/* Print repro steps for failed tests */
|
||||
if (failedNumberOfTests > 0) {
|
||||
SDLTest_Log("Harness input to repro failures:");
|
||||
for (testCounter = 0; testCounter < failedNumberOfTests; testCounter++) {
|
||||
SDLTest_Log(COLOR_RED " --seed %s --filter %s" COLOR_END, runSeed, failedTests[testCounter]->name);
|
||||
}
|
||||
}
|
||||
SDL_free((void *)failedTests);
|
||||
|
||||
SDLTest_Log("Exit code: %d", runResult);
|
||||
return runResult;
|
||||
}
|
111
external/sdl/SDL/src/test/SDL_test_log.c
vendored
Normal file
111
external/sdl/SDL/src/test/SDL_test_log.c
vendored
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Used by the test framework and test cases.
|
||||
|
||||
*/
|
||||
|
||||
/* quiet windows compiler warnings */
|
||||
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
#include <SDL3/SDL_test.h>
|
||||
|
||||
#include <time.h> /* Needed for localtime() */
|
||||
|
||||
/* work around compiler warning on older GCCs. */
|
||||
#if (defined(__GNUC__) && (__GNUC__ <= 2))
|
||||
static size_t strftime_gcc2_workaround(char *s, size_t max, const char *fmt, const struct tm *tm)
|
||||
{
|
||||
return strftime(s, max, fmt, tm);
|
||||
}
|
||||
#ifdef strftime
|
||||
#undef strftime
|
||||
#endif
|
||||
#define strftime strftime_gcc2_workaround
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Converts unix timestamp to its ascii representation in localtime
|
||||
*
|
||||
* Note: Uses a static buffer internally, so the return value
|
||||
* isn't valid after the next call of this function. If you
|
||||
* want to retain the return value, make a copy of it.
|
||||
*
|
||||
* \param timestamp A Timestamp, i.e. time(0)
|
||||
*
|
||||
* \return Ascii representation of the timestamp in localtime in the format '08/23/01 14:55:02'
|
||||
*/
|
||||
static const char *SDLTest_TimestampToString(const time_t timestamp)
|
||||
{
|
||||
time_t copy;
|
||||
static char buffer[64];
|
||||
struct tm *local;
|
||||
size_t result = 0;
|
||||
|
||||
SDL_memset(buffer, 0, sizeof(buffer));
|
||||
copy = timestamp;
|
||||
local = localtime(©);
|
||||
result = strftime(buffer, sizeof(buffer), "%x %X", local);
|
||||
if (result == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prints given message with a timestamp in the TEST category and INFO priority.
|
||||
*/
|
||||
void SDLTest_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
||||
{
|
||||
va_list list;
|
||||
char logMessage[SDLTEST_MAX_LOGMESSAGE_LENGTH];
|
||||
|
||||
/* Print log message into a buffer */
|
||||
SDL_memset(logMessage, 0, SDLTEST_MAX_LOGMESSAGE_LENGTH);
|
||||
va_start(list, fmt);
|
||||
(void)SDL_vsnprintf(logMessage, SDLTEST_MAX_LOGMESSAGE_LENGTH - 1, fmt, list);
|
||||
va_end(list);
|
||||
|
||||
/* Log with timestamp and newline */
|
||||
SDL_LogMessage(SDL_LOG_CATEGORY_TEST, SDL_LOG_PRIORITY_INFO, " %s: %s", SDLTest_TimestampToString(time(0)), logMessage);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prints given message with a timestamp in the TEST category and the ERROR priority.
|
||||
*/
|
||||
void SDLTest_LogError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
||||
{
|
||||
va_list list;
|
||||
char logMessage[SDLTEST_MAX_LOGMESSAGE_LENGTH];
|
||||
|
||||
/* Print log message into a buffer */
|
||||
SDL_memset(logMessage, 0, SDLTEST_MAX_LOGMESSAGE_LENGTH);
|
||||
va_start(list, fmt);
|
||||
(void)SDL_vsnprintf(logMessage, SDLTEST_MAX_LOGMESSAGE_LENGTH - 1, fmt, list);
|
||||
va_end(list);
|
||||
|
||||
/* Log with timestamp and newline */
|
||||
SDL_LogMessage(SDL_LOG_CATEGORY_TEST, SDL_LOG_PRIORITY_ERROR, "%s: %s", SDLTest_TimestampToString(time(0)), logMessage);
|
||||
}
|
342
external/sdl/SDL/src/test/SDL_test_md5.c
vendored
Normal file
342
external/sdl/SDL/src/test/SDL_test_md5.c
vendored
Normal file
@ -0,0 +1,342 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
***********************************************************************
|
||||
** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
|
||||
** Created: 2/17/90 RLR **
|
||||
** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. **
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
***********************************************************************
|
||||
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
|
||||
** **
|
||||
** License to copy and use this software is granted provided that **
|
||||
** it is identified as the "RSA Data Security, Inc. MD5 Message- **
|
||||
** Digest Algorithm" in all material mentioning or referencing this **
|
||||
** software or this function. **
|
||||
** **
|
||||
** License is also granted to make and use derivative works **
|
||||
** provided that such works are identified as "derived from the RSA **
|
||||
** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
|
||||
** material mentioning or referencing the derived work. **
|
||||
** **
|
||||
** RSA Data Security, Inc. makes no representations concerning **
|
||||
** either the merchantability of this software or the suitability **
|
||||
** of this software for any particular purpose. It is provided "as **
|
||||
** is" without express or implied warranty of any kind. **
|
||||
** **
|
||||
** These notices must be retained in any copies of any part of this **
|
||||
** documentation and/or software. **
|
||||
***********************************************************************
|
||||
*/
|
||||
#include <SDL3/SDL_test.h>
|
||||
|
||||
/* Forward declaration of static helper function */
|
||||
static void SDLTest_Md5Transform(MD5UINT4 *buf, const MD5UINT4 *in);
|
||||
|
||||
static unsigned char MD5PADDING[64] = {
|
||||
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/* F, G, H and I are basic MD5 functions */
|
||||
#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & (~(z))))
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define I(x, y, z) ((y) ^ ((x) | (~(z))))
|
||||
|
||||
/* ROTATE_LEFT rotates x left n bits */
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
|
||||
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
|
||||
|
||||
/* Rotation is separate from addition to prevent recomputation */
|
||||
#define FF(a, b, c, d, x, s, ac) \
|
||||
{ \
|
||||
(a) += F((b), (c), (d)) + (x) + (MD5UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define GG(a, b, c, d, x, s, ac) \
|
||||
{ \
|
||||
(a) += G((b), (c), (d)) + (x) + (MD5UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define HH(a, b, c, d, x, s, ac) \
|
||||
{ \
|
||||
(a) += H((b), (c), (d)) + (x) + (MD5UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define II(a, b, c, d, x, s, ac) \
|
||||
{ \
|
||||
(a) += I((b), (c), (d)) + (x) + (MD5UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
|
||||
/*
|
||||
The routine MD5Init initializes the message-digest context
|
||||
mdContext. All fields are set to zero.
|
||||
*/
|
||||
|
||||
void SDLTest_Md5Init(SDLTest_Md5Context *mdContext)
|
||||
{
|
||||
if (mdContext == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
mdContext->i[0] = mdContext->i[1] = (MD5UINT4)0;
|
||||
|
||||
/*
|
||||
* Load magic initialization constants.
|
||||
*/
|
||||
mdContext->buf[0] = (MD5UINT4)0x67452301;
|
||||
mdContext->buf[1] = (MD5UINT4)0xefcdab89;
|
||||
mdContext->buf[2] = (MD5UINT4)0x98badcfe;
|
||||
mdContext->buf[3] = (MD5UINT4)0x10325476;
|
||||
}
|
||||
|
||||
/*
|
||||
The routine MD5Update updates the message-digest context to
|
||||
account for the presence of each of the characters inBuf[0..inLen-1]
|
||||
in the message whose digest is being computed.
|
||||
*/
|
||||
|
||||
void SDLTest_Md5Update(SDLTest_Md5Context *mdContext, unsigned char *inBuf,
|
||||
unsigned int inLen)
|
||||
{
|
||||
MD5UINT4 in[16];
|
||||
int mdi;
|
||||
unsigned int i, ii;
|
||||
|
||||
if (mdContext == NULL) {
|
||||
return;
|
||||
}
|
||||
if (inBuf == NULL || inLen < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* compute number of bytes mod 64
|
||||
*/
|
||||
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
|
||||
|
||||
/*
|
||||
* update number of bits
|
||||
*/
|
||||
if ((mdContext->i[0] + ((MD5UINT4)inLen << 3)) < mdContext->i[0]) {
|
||||
mdContext->i[1]++;
|
||||
}
|
||||
mdContext->i[0] += ((MD5UINT4)inLen << 3);
|
||||
mdContext->i[1] += ((MD5UINT4)inLen >> 29);
|
||||
|
||||
while (inLen--) {
|
||||
/*
|
||||
* add new character to buffer, increment mdi
|
||||
*/
|
||||
mdContext->in[mdi++] = *inBuf++;
|
||||
|
||||
/*
|
||||
* transform if necessary
|
||||
*/
|
||||
if (mdi == 0x40) {
|
||||
for (i = 0, ii = 0; i < 16; i++, ii += 4) {
|
||||
in[i] = (((MD5UINT4)mdContext->in[ii + 3]) << 24) | (((MD5UINT4)mdContext->in[ii + 2]) << 16) | (((MD5UINT4)mdContext->in[ii + 1]) << 8) | ((MD5UINT4)mdContext->in[ii]);
|
||||
}
|
||||
SDLTest_Md5Transform(mdContext->buf, in);
|
||||
mdi = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
The routine MD5Final terminates the message-digest computation and
|
||||
ends with the desired message digest in mdContext->digest[0...15].
|
||||
*/
|
||||
|
||||
void SDLTest_Md5Final(SDLTest_Md5Context *mdContext)
|
||||
{
|
||||
MD5UINT4 in[16];
|
||||
int mdi;
|
||||
unsigned int i, ii;
|
||||
unsigned int padLen;
|
||||
|
||||
if (mdContext == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* save number of bits
|
||||
*/
|
||||
in[14] = mdContext->i[0];
|
||||
in[15] = mdContext->i[1];
|
||||
|
||||
/*
|
||||
* compute number of bytes mod 64
|
||||
*/
|
||||
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
|
||||
|
||||
/*
|
||||
* pad out to 56 mod 64
|
||||
*/
|
||||
padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
|
||||
SDLTest_Md5Update(mdContext, MD5PADDING, padLen);
|
||||
|
||||
/*
|
||||
* append length in bits and transform
|
||||
*/
|
||||
for (i = 0, ii = 0; i < 14; i++, ii += 4) {
|
||||
in[i] = (((MD5UINT4)mdContext->in[ii + 3]) << 24) | (((MD5UINT4)mdContext->in[ii + 2]) << 16) | (((MD5UINT4)mdContext->in[ii + 1]) << 8) | ((MD5UINT4)mdContext->in[ii]);
|
||||
}
|
||||
SDLTest_Md5Transform(mdContext->buf, in);
|
||||
|
||||
/*
|
||||
* store buffer in digest
|
||||
*/
|
||||
for (i = 0, ii = 0; i < 4; i++, ii += 4) {
|
||||
mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
|
||||
mdContext->digest[ii + 1] =
|
||||
(unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
|
||||
mdContext->digest[ii + 2] =
|
||||
(unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
|
||||
mdContext->digest[ii + 3] =
|
||||
(unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
/* Basic MD5 step. Transforms buf based on in.
|
||||
*/
|
||||
static void SDLTest_Md5Transform(MD5UINT4 *buf, const MD5UINT4 *in)
|
||||
{
|
||||
MD5UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
|
||||
|
||||
/*
|
||||
* Round 1
|
||||
*/
|
||||
#define S11 7
|
||||
#define S12 12
|
||||
#define S13 17
|
||||
#define S14 22
|
||||
FF(a, b, c, d, in[0], S11, 3614090360u); /* 1 */
|
||||
FF(d, a, b, c, in[1], S12, 3905402710u); /* 2 */
|
||||
FF(c, d, a, b, in[2], S13, 606105819u); /* 3 */
|
||||
FF(b, c, d, a, in[3], S14, 3250441966u); /* 4 */
|
||||
FF(a, b, c, d, in[4], S11, 4118548399u); /* 5 */
|
||||
FF(d, a, b, c, in[5], S12, 1200080426u); /* 6 */
|
||||
FF(c, d, a, b, in[6], S13, 2821735955u); /* 7 */
|
||||
FF(b, c, d, a, in[7], S14, 4249261313u); /* 8 */
|
||||
FF(a, b, c, d, in[8], S11, 1770035416u); /* 9 */
|
||||
FF(d, a, b, c, in[9], S12, 2336552879u); /* 10 */
|
||||
FF(c, d, a, b, in[10], S13, 4294925233u); /* 11 */
|
||||
FF(b, c, d, a, in[11], S14, 2304563134u); /* 12 */
|
||||
FF(a, b, c, d, in[12], S11, 1804603682u); /* 13 */
|
||||
FF(d, a, b, c, in[13], S12, 4254626195u); /* 14 */
|
||||
FF(c, d, a, b, in[14], S13, 2792965006u); /* 15 */
|
||||
FF(b, c, d, a, in[15], S14, 1236535329u); /* 16 */
|
||||
|
||||
/*
|
||||
* Round 2
|
||||
*/
|
||||
#define S21 5
|
||||
#define S22 9
|
||||
#define S23 14
|
||||
#define S24 20
|
||||
GG(a, b, c, d, in[1], S21, 4129170786u); /* 17 */
|
||||
GG(d, a, b, c, in[6], S22, 3225465664u); /* 18 */
|
||||
GG(c, d, a, b, in[11], S23, 643717713u); /* 19 */
|
||||
GG(b, c, d, a, in[0], S24, 3921069994u); /* 20 */
|
||||
GG(a, b, c, d, in[5], S21, 3593408605u); /* 21 */
|
||||
GG(d, a, b, c, in[10], S22, 38016083u); /* 22 */
|
||||
GG(c, d, a, b, in[15], S23, 3634488961u); /* 23 */
|
||||
GG(b, c, d, a, in[4], S24, 3889429448u); /* 24 */
|
||||
GG(a, b, c, d, in[9], S21, 568446438u); /* 25 */
|
||||
GG(d, a, b, c, in[14], S22, 3275163606u); /* 26 */
|
||||
GG(c, d, a, b, in[3], S23, 4107603335u); /* 27 */
|
||||
GG(b, c, d, a, in[8], S24, 1163531501u); /* 28 */
|
||||
GG(a, b, c, d, in[13], S21, 2850285829u); /* 29 */
|
||||
GG(d, a, b, c, in[2], S22, 4243563512u); /* 30 */
|
||||
GG(c, d, a, b, in[7], S23, 1735328473u); /* 31 */
|
||||
GG(b, c, d, a, in[12], S24, 2368359562u); /* 32 */
|
||||
|
||||
/*
|
||||
* Round 3
|
||||
*/
|
||||
#define S31 4
|
||||
#define S32 11
|
||||
#define S33 16
|
||||
#define S34 23
|
||||
HH(a, b, c, d, in[5], S31, 4294588738u); /* 33 */
|
||||
HH(d, a, b, c, in[8], S32, 2272392833u); /* 34 */
|
||||
HH(c, d, a, b, in[11], S33, 1839030562u); /* 35 */
|
||||
HH(b, c, d, a, in[14], S34, 4259657740u); /* 36 */
|
||||
HH(a, b, c, d, in[1], S31, 2763975236u); /* 37 */
|
||||
HH(d, a, b, c, in[4], S32, 1272893353u); /* 38 */
|
||||
HH(c, d, a, b, in[7], S33, 4139469664u); /* 39 */
|
||||
HH(b, c, d, a, in[10], S34, 3200236656u); /* 40 */
|
||||
HH(a, b, c, d, in[13], S31, 681279174u); /* 41 */
|
||||
HH(d, a, b, c, in[0], S32, 3936430074u); /* 42 */
|
||||
HH(c, d, a, b, in[3], S33, 3572445317u); /* 43 */
|
||||
HH(b, c, d, a, in[6], S34, 76029189u); /* 44 */
|
||||
HH(a, b, c, d, in[9], S31, 3654602809u); /* 45 */
|
||||
HH(d, a, b, c, in[12], S32, 3873151461u); /* 46 */
|
||||
HH(c, d, a, b, in[15], S33, 530742520u); /* 47 */
|
||||
HH(b, c, d, a, in[2], S34, 3299628645u); /* 48 */
|
||||
|
||||
/*
|
||||
* Round 4
|
||||
*/
|
||||
#define S41 6
|
||||
#define S42 10
|
||||
#define S43 15
|
||||
#define S44 21
|
||||
II(a, b, c, d, in[0], S41, 4096336452u); /* 49 */
|
||||
II(d, a, b, c, in[7], S42, 1126891415u); /* 50 */
|
||||
II(c, d, a, b, in[14], S43, 2878612391u); /* 51 */
|
||||
II(b, c, d, a, in[5], S44, 4237533241u); /* 52 */
|
||||
II(a, b, c, d, in[12], S41, 1700485571u); /* 53 */
|
||||
II(d, a, b, c, in[3], S42, 2399980690u); /* 54 */
|
||||
II(c, d, a, b, in[10], S43, 4293915773u); /* 55 */
|
||||
II(b, c, d, a, in[1], S44, 2240044497u); /* 56 */
|
||||
II(a, b, c, d, in[8], S41, 1873313359u); /* 57 */
|
||||
II(d, a, b, c, in[15], S42, 4264355552u); /* 58 */
|
||||
II(c, d, a, b, in[6], S43, 2734768916u); /* 59 */
|
||||
II(b, c, d, a, in[13], S44, 1309151649u); /* 60 */
|
||||
II(a, b, c, d, in[4], S41, 4149444226u); /* 61 */
|
||||
II(d, a, b, c, in[11], S42, 3174756917u); /* 62 */
|
||||
II(c, d, a, b, in[2], S43, 718787259u); /* 63 */
|
||||
II(b, c, d, a, in[9], S44, 3951481745u); /* 64 */
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
274
external/sdl/SDL/src/test/SDL_test_memory.c
vendored
Normal file
274
external/sdl/SDL/src/test/SDL_test_memory.c
vendored
Normal file
@ -0,0 +1,274 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include <SDL3/SDL_test.h>
|
||||
|
||||
#ifdef HAVE_LIBUNWIND_H
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#endif
|
||||
|
||||
/* This is a simple tracking allocator to demonstrate the use of SDL's
|
||||
memory allocation replacement functionality.
|
||||
|
||||
It gets slow with large numbers of allocations and shouldn't be used
|
||||
for production code.
|
||||
*/
|
||||
|
||||
typedef struct SDL_tracked_allocation
|
||||
{
|
||||
void *mem;
|
||||
size_t size;
|
||||
Uint64 stack[10];
|
||||
char stack_names[10][256];
|
||||
struct SDL_tracked_allocation *next;
|
||||
} SDL_tracked_allocation;
|
||||
|
||||
static SDLTest_Crc32Context s_crc32_context;
|
||||
static SDL_malloc_func SDL_malloc_orig = NULL;
|
||||
static SDL_calloc_func SDL_calloc_orig = NULL;
|
||||
static SDL_realloc_func SDL_realloc_orig = NULL;
|
||||
static SDL_free_func SDL_free_orig = NULL;
|
||||
static int s_previous_allocations = 0;
|
||||
static SDL_tracked_allocation *s_tracked_allocations[256];
|
||||
|
||||
static unsigned int get_allocation_bucket(void *mem)
|
||||
{
|
||||
CrcUint32 crc_value;
|
||||
unsigned int index;
|
||||
SDLTest_Crc32Calc(&s_crc32_context, (CrcUint8 *)&mem, sizeof(mem), &crc_value);
|
||||
index = (crc_value & (SDL_arraysize(s_tracked_allocations) - 1));
|
||||
return index;
|
||||
}
|
||||
|
||||
static SDL_bool SDL_IsAllocationTracked(void *mem)
|
||||
{
|
||||
SDL_tracked_allocation *entry;
|
||||
int index = get_allocation_bucket(mem);
|
||||
for (entry = s_tracked_allocations[index]; entry; entry = entry->next) {
|
||||
if (mem == entry->mem) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
static void SDL_TrackAllocation(void *mem, size_t size)
|
||||
{
|
||||
SDL_tracked_allocation *entry;
|
||||
int index = get_allocation_bucket(mem);
|
||||
|
||||
if (SDL_IsAllocationTracked(mem)) {
|
||||
return;
|
||||
}
|
||||
entry = (SDL_tracked_allocation *)SDL_malloc_orig(sizeof(*entry));
|
||||
if (entry == NULL) {
|
||||
return;
|
||||
}
|
||||
entry->mem = mem;
|
||||
entry->size = size;
|
||||
|
||||
/* Generate the stack trace for the allocation */
|
||||
SDL_zeroa(entry->stack);
|
||||
#ifdef HAVE_LIBUNWIND_H
|
||||
{
|
||||
int stack_index;
|
||||
unw_cursor_t cursor;
|
||||
unw_context_t context;
|
||||
|
||||
unw_getcontext(&context);
|
||||
unw_init_local(&cursor, &context);
|
||||
|
||||
stack_index = 0;
|
||||
while (unw_step(&cursor) > 0) {
|
||||
unw_word_t offset, pc;
|
||||
char sym[236];
|
||||
|
||||
unw_get_reg(&cursor, UNW_REG_IP, &pc);
|
||||
entry->stack[stack_index] = pc;
|
||||
|
||||
if (unw_get_proc_name(&cursor, sym, sizeof(sym), &offset) == 0) {
|
||||
SDL_snprintf(entry->stack_names[stack_index], sizeof(entry->stack_names[stack_index]), "%s+0x%llx", sym, (unsigned long long)offset);
|
||||
}
|
||||
++stack_index;
|
||||
|
||||
if (stack_index == SDL_arraysize(entry->stack)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_LIBUNWIND_H */
|
||||
|
||||
entry->next = s_tracked_allocations[index];
|
||||
s_tracked_allocations[index] = entry;
|
||||
}
|
||||
|
||||
static void SDL_UntrackAllocation(void *mem)
|
||||
{
|
||||
SDL_tracked_allocation *entry, *prev;
|
||||
int index = get_allocation_bucket(mem);
|
||||
|
||||
prev = NULL;
|
||||
for (entry = s_tracked_allocations[index]; entry; entry = entry->next) {
|
||||
if (mem == entry->mem) {
|
||||
if (prev) {
|
||||
prev->next = entry->next;
|
||||
} else {
|
||||
s_tracked_allocations[index] = entry->next;
|
||||
}
|
||||
SDL_free_orig(entry);
|
||||
return;
|
||||
}
|
||||
prev = entry;
|
||||
}
|
||||
}
|
||||
|
||||
static void *SDLCALL SDLTest_TrackedMalloc(size_t size)
|
||||
{
|
||||
void *mem;
|
||||
|
||||
mem = SDL_malloc_orig(size);
|
||||
if (mem) {
|
||||
SDL_TrackAllocation(mem, size);
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
static void *SDLCALL SDLTest_TrackedCalloc(size_t nmemb, size_t size)
|
||||
{
|
||||
void *mem;
|
||||
|
||||
mem = SDL_calloc_orig(nmemb, size);
|
||||
if (mem) {
|
||||
SDL_TrackAllocation(mem, nmemb * size);
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
static void *SDLCALL SDLTest_TrackedRealloc(void *ptr, size_t size)
|
||||
{
|
||||
void *mem;
|
||||
|
||||
SDL_assert(ptr == NULL || SDL_IsAllocationTracked(ptr));
|
||||
mem = SDL_realloc_orig(ptr, size);
|
||||
if (mem && mem != ptr) {
|
||||
if (ptr) {
|
||||
SDL_UntrackAllocation(ptr);
|
||||
}
|
||||
SDL_TrackAllocation(mem, size);
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
static void SDLCALL SDLTest_TrackedFree(void *ptr)
|
||||
{
|
||||
if (ptr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!s_previous_allocations) {
|
||||
SDL_assert(SDL_IsAllocationTracked(ptr));
|
||||
}
|
||||
SDL_UntrackAllocation(ptr);
|
||||
SDL_free_orig(ptr);
|
||||
}
|
||||
|
||||
int SDLTest_TrackAllocations(void)
|
||||
{
|
||||
if (SDL_malloc_orig) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDLTest_Crc32Init(&s_crc32_context);
|
||||
|
||||
s_previous_allocations = SDL_GetNumAllocations();
|
||||
if (s_previous_allocations != 0) {
|
||||
SDL_Log("SDLTest_TrackAllocations(): There are %d previous allocations, disabling free() validation", s_previous_allocations);
|
||||
}
|
||||
|
||||
SDL_GetMemoryFunctions(&SDL_malloc_orig,
|
||||
&SDL_calloc_orig,
|
||||
&SDL_realloc_orig,
|
||||
&SDL_free_orig);
|
||||
|
||||
SDL_SetMemoryFunctions(SDLTest_TrackedMalloc,
|
||||
SDLTest_TrackedCalloc,
|
||||
SDLTest_TrackedRealloc,
|
||||
SDLTest_TrackedFree);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SDLTest_LogAllocations(void)
|
||||
{
|
||||
char *message = NULL;
|
||||
size_t message_size = 0;
|
||||
char line[128], *tmp;
|
||||
SDL_tracked_allocation *entry;
|
||||
int index, count, stack_index;
|
||||
Uint64 total_allocated;
|
||||
|
||||
if (!SDL_malloc_orig) {
|
||||
return;
|
||||
}
|
||||
|
||||
message = SDL_realloc_orig(NULL, 1);
|
||||
if (!message) {
|
||||
return;
|
||||
}
|
||||
*message = 0;
|
||||
|
||||
#define ADD_LINE() \
|
||||
message_size += (SDL_strlen(line) + 1); \
|
||||
tmp = (char *)SDL_realloc_orig(message, message_size); \
|
||||
if (!tmp) { \
|
||||
return; \
|
||||
} \
|
||||
message = tmp; \
|
||||
SDL_strlcat(message, line, message_size)
|
||||
|
||||
SDL_strlcpy(line, "Memory allocations:\n", sizeof(line));
|
||||
ADD_LINE();
|
||||
SDL_strlcpy(line, "Expect 2 allocations from within SDL_GetErrBuf()\n", sizeof(line));
|
||||
ADD_LINE();
|
||||
|
||||
count = 0;
|
||||
total_allocated = 0;
|
||||
for (index = 0; index < SDL_arraysize(s_tracked_allocations); ++index) {
|
||||
for (entry = s_tracked_allocations[index]; entry; entry = entry->next) {
|
||||
(void)SDL_snprintf(line, sizeof(line), "Allocation %d: %d bytes\n", count, (int)entry->size);
|
||||
ADD_LINE();
|
||||
/* Start at stack index 1 to skip our tracking functions */
|
||||
for (stack_index = 1; stack_index < SDL_arraysize(entry->stack); ++stack_index) {
|
||||
if (!entry->stack[stack_index]) {
|
||||
break;
|
||||
}
|
||||
(void)SDL_snprintf(line, sizeof(line), "\t0x%" SDL_PRIx64 ": %s\n", entry->stack[stack_index], entry->stack_names[stack_index]);
|
||||
ADD_LINE();
|
||||
}
|
||||
total_allocated += entry->size;
|
||||
++count;
|
||||
}
|
||||
}
|
||||
(void)SDL_snprintf(line, sizeof(line), "Total: %.2f Kb in %d allocations\n", total_allocated / 1024.0, count);
|
||||
ADD_LINE();
|
||||
#undef ADD_LINE
|
||||
|
||||
SDL_Log("%s", message);
|
||||
}
|
98
external/sdl/SDL/src/test/SDL_test_random.c
vendored
Normal file
98
external/sdl/SDL/src/test/SDL_test_random.c
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
A portable "32-bit Multiply with carry" random number generator.
|
||||
|
||||
Used by the fuzzer component.
|
||||
Original source code contributed by A. Schiffler for GSOC project.
|
||||
|
||||
*/
|
||||
#include <SDL3/SDL_test.h>
|
||||
|
||||
#include <stdlib.h> /* Needed for srand() and rand() */
|
||||
#include <time.h> /* Needed for time() */
|
||||
|
||||
/* Initialize random number generator with two integer variables */
|
||||
|
||||
void SDLTest_RandomInit(SDLTest_RandomContext *rndContext, unsigned int xi, unsigned int ci)
|
||||
{
|
||||
if (rndContext == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Choose a value for 'a' from this list
|
||||
* 1791398085 1929682203 1683268614 1965537969 1675393560
|
||||
* 1967773755 1517746329 1447497129 1655692410 1606218150
|
||||
* 2051013963 1075433238 1557985959 1781943330 1893513180
|
||||
* 1631296680 2131995753 2083801278 1873196400 1554115554
|
||||
*/
|
||||
rndContext->a = 1655692410;
|
||||
rndContext->x = 30903;
|
||||
rndContext->c = 0;
|
||||
if (xi != 0) {
|
||||
rndContext->x = xi;
|
||||
}
|
||||
rndContext->c = ci;
|
||||
rndContext->ah = rndContext->a >> 16;
|
||||
rndContext->al = rndContext->a & 65535;
|
||||
}
|
||||
|
||||
/* Initialize random number generator from system time */
|
||||
|
||||
void SDLTest_RandomInitTime(SDLTest_RandomContext *rndContext)
|
||||
{
|
||||
int a, b;
|
||||
|
||||
if (rndContext == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
srand((unsigned int)time(NULL));
|
||||
a = rand();
|
||||
srand((unsigned int)SDL_GetPerformanceCounter());
|
||||
b = rand();
|
||||
SDLTest_RandomInit(rndContext, a, b);
|
||||
}
|
||||
|
||||
/* Returns random numbers */
|
||||
|
||||
unsigned int SDLTest_Random(SDLTest_RandomContext *rndContext)
|
||||
{
|
||||
unsigned int xh, xl;
|
||||
|
||||
if (rndContext == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
xh = rndContext->x >> 16;
|
||||
xl = rndContext->x & 65535;
|
||||
rndContext->x = rndContext->x * rndContext->a + rndContext->c;
|
||||
rndContext->c =
|
||||
xh * rndContext->ah + ((xh * rndContext->al) >> 16) +
|
||||
((xl * rndContext->ah) >> 16);
|
||||
if (xl * rndContext->al >= (~rndContext->c + 1)) {
|
||||
rndContext->c++;
|
||||
}
|
||||
return rndContext->x;
|
||||
}
|
Reference in New Issue
Block a user