src/test/SDL_test_fuzzer.c
author Andreas Schiffler <aschiffler@ferzkopp.net>
Sat, 12 Jan 2013 22:58:12 -0800
changeset 6811 60d95fcfaf3c
parent 6789 7177d421bb07
child 6839 2494f667555c
permissions -rw-r--r--
Update SDL_InvalidParamError to take param name; add additional fuzzer function; add new tests to keyboard test suite; improve surface test suite
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 
    22 /* 
    23 
    24   Data generators for fuzzing test data in a reproducible way.
    25  
    26 */
    27 
    28 #include "SDL_config.h"
    29 
    30 /* Visual Studio 2008 doesn't have stdint.h */
    31 #if defined(_MSC_VER) && _MSC_VER <= 1500
    32 #define UINT8_MAX   ~(Uint8)0
    33 #define UINT16_MAX  ~(Uint16)0
    34 #define UINT32_MAX  ~(Uint32)0
    35 #define UINT64_MAX  ~(Uint64)0
    36 #else
    37 #include <stdint.h>
    38 #endif
    39 #include <stdio.h>
    40 #include <stdlib.h>
    41 #include <limits.h>
    42 #include <float.h>
    43 
    44 #include "SDL_test.h"
    45 
    46 /** 
    47  *Counter for fuzzer invocations
    48  */
    49 static int fuzzerInvocationCounter = 0;
    50 
    51 /**
    52  * Context for shared random number generator
    53  */
    54 static SDLTest_RandomContext rndContext;
    55 
    56 /*
    57  * Note: doxygen documentation markup for functions is in the header file.
    58  */
    59 
    60 void
    61 SDLTest_FuzzerInit(Uint64 execKey)
    62 {
    63 	Uint32 a = (execKey >> 32) & 0x00000000FFFFFFFF;
    64 	Uint32 b = execKey & 0x00000000FFFFFFFF;
    65 	SDL_memset((void *)&rndContext, 0, sizeof(SDLTest_RandomContext));
    66 	SDLTest_RandomInit(&rndContext, a, b);
    67 	fuzzerInvocationCounter = 0;
    68 }
    69 
    70 int
    71 SDLTest_GetFuzzerInvocationCount()
    72 {
    73 	return fuzzerInvocationCounter;
    74 }
    75 
    76 Uint8
    77 SDLTest_RandomUint8()
    78 {
    79 	fuzzerInvocationCounter++;
    80 
    81 	return (Uint8) SDLTest_RandomInt(&rndContext) & 0x000000FF;
    82 }
    83 
    84 Sint8
    85 SDLTest_RandomSint8()
    86 {
    87 	fuzzerInvocationCounter++;
    88 
    89 	return (Sint8) SDLTest_RandomInt(&rndContext) & 0x000000FF;
    90 }
    91 
    92 Uint16
    93 SDLTest_RandomUint16()
    94 {
    95 	fuzzerInvocationCounter++;
    96 
    97 	return (Uint16) SDLTest_RandomInt(&rndContext) & 0x0000FFFF;
    98 }
    99 
   100 Sint16
   101 SDLTest_RandomSint16()
   102 {
   103 	fuzzerInvocationCounter++;
   104 
   105 	return (Sint16) SDLTest_RandomInt(&rndContext) & 0x0000FFFF;
   106 }
   107 
   108 Sint32
   109 SDLTest_RandomSint32()
   110 {
   111 	fuzzerInvocationCounter++;
   112 
   113 	return (Sint32) SDLTest_RandomInt(&rndContext);
   114 }
   115 
   116 Uint32
   117 SDLTest_RandomUint32()
   118 {
   119 	fuzzerInvocationCounter++;
   120 
   121 	return (Uint32) SDLTest_RandomInt(&rndContext);
   122 }
   123 
   124 Uint64
   125 SDLTest_RandomUint64()
   126 {
   127 	Uint64 value = 0;
   128 	Uint32 *vp = (void *)&value;
   129 
   130 	fuzzerInvocationCounter++;
   131 
   132 	vp[0] = SDLTest_RandomSint32();
   133 	vp[1] = SDLTest_RandomSint32();
   134 
   135 	return value;
   136 }
   137 
   138 Sint64
   139 SDLTest_RandomSint64()
   140 {
   141 	Uint64 value = 0;
   142 	Uint32 *vp = (void *)&value;
   143 
   144 	fuzzerInvocationCounter++;
   145 
   146 	vp[0] = SDLTest_RandomSint32();
   147 	vp[1] = SDLTest_RandomSint32();
   148 
   149 	return value;
   150 }
   151 
   152 
   153 
   154 Sint32
   155 SDLTest_RandomIntegerInRange(Sint32 pMin, Sint32 pMax)
   156 {
   157 	Sint64 min = pMin;
   158 	Sint64 max = pMax;
   159 	Sint64 temp;
   160 	Sint64 number;
   161 
   162 	if(pMin > pMax) {
   163 		temp = min;
   164 		min = max;
   165 		max = temp;
   166 	} else if(pMin == pMax) {
   167 		return (Sint32)min;
   168 	}
   169 
   170 	number = SDLTest_RandomUint32(); // invocation count increment in there
   171 
   172 	return (Sint32)((number % ((max + 1) - min)) + min);
   173 }
   174 
   175 /*!
   176  * Generates boundary values between the given boundaries.
   177  * Boundary values are inclusive. See the examples below.
   178  * If boundary2 < boundary1, the values are swapped.
   179  * If boundary1 == boundary2, value of boundary1 will be returned
   180  *
   181  * Generating boundary values for Uint8:
   182  * BoundaryValues(sizeof(Uint8), 10, 20, True) -> [10,11,19,20]
   183  * BoundaryValues(sizeof(Uint8), 10, 20, False) -> [9,21]
   184  * BoundaryValues(sizeof(Uint8), 0, 15, True) -> [0, 1, 14, 15]
   185  * BoundaryValues(sizeof(Uint8), 0, 15, False) -> [16]
   186  * BoundaryValues(sizeof(Uint8), 0, 255, False) -> NULL
   187  *
   188  * Generator works the same for other types of unsigned integers.
   189  *
   190  * Note: outBuffer will be allocated and needs to be freed later.
   191  * If outbuffer != NULL, it'll be freed.
   192  *
   193  * \param maxValue The biggest value that is acceptable for this data type.
   194  * 					For instance, for Uint8 -> 255, Uint16 -> 65536 etc.
   195  * \param pBoundary1 defines lower boundary
   196  * \param pBoundary2 defines upper boundary
   197  * \param validDomain Generate only for valid domain (for the data type)
   198  *
   199  * \param outBuffer The generated boundary values are put here
   200  *
   201  * \returns Returns the number of elements in outBuffer or -1 in case of error
   202  */
   203 Uint32
   204 SDLTest_GenerateUnsignedBoundaryValues(const Uint64 maxValue,
   205 					Uint64 pBoundary1, Uint64 pBoundary2, SDL_bool validDomain,
   206 					Uint64 *outBuffer)
   207 {
   208 	Uint64 boundary1 = pBoundary1, boundary2 = pBoundary2;
   209 	Uint64 temp;
   210 	Uint64 tempBuf[4];
   211 	int index;
   212 
   213 	if(outBuffer != NULL) {
   214 		SDL_free(outBuffer);
   215 	}
   216 
   217 	if(boundary1 > boundary2) {
   218 		temp = boundary1;
   219 		boundary1 = boundary2;
   220 		boundary2 = temp;
   221 	}
   222 
   223 	index = 0;
   224 	if(boundary1 == boundary2) {
   225 		tempBuf[index++] = boundary1;
   226 	}
   227 	else if(validDomain) {
   228 		tempBuf[index++] = boundary1;
   229 
   230 		if(boundary1 < UINT64_MAX)
   231 			tempBuf[index++] = boundary1 + 1;
   232 
   233 		tempBuf[index++] = boundary2 - 1;
   234 		tempBuf[index++] = boundary2;
   235 	}
   236 	else {
   237 		if(boundary1 > 0) {
   238 			tempBuf[index++] = boundary1 - 1;
   239 		}
   240 
   241 		if(boundary2 < maxValue && boundary2 < UINT64_MAX) {
   242 			tempBuf[index++] = boundary2 + 1;
   243 		}
   244 	}
   245 
   246 	if(index == 0) {
   247 		// There are no valid boundaries
   248 		return 0;
   249 	}
   250 
   251 	// Create the return buffer
   252 	outBuffer = (Uint64 *)SDL_malloc(index * sizeof(Uint64));
   253 	if(outBuffer == NULL) {
   254 		return 0;
   255 	}
   256 
   257 	SDL_memcpy(outBuffer, tempBuf, index * sizeof(Uint64));
   258 
   259 	return index;
   260 }
   261 
   262 Uint8
   263 SDLTest_RandomUint8BoundaryValue(Uint8 boundary1, Uint8 boundary2, SDL_bool validDomain)
   264 {
   265 	Uint64 *buffer = NULL;
   266 	Uint32 size;
   267 	Uint32 index;
   268 	Uint8 retVal;
   269 
   270 	// max value for Uint8
   271 	const Uint64 maxValue = UINT8_MAX;
   272 
   273 	size = SDLTest_GenerateUnsignedBoundaryValues(maxValue,
   274 				(Uint64) boundary1, (Uint64) boundary2,
   275 				validDomain, buffer);
   276 	if (buffer == NULL || size == 0) {
   277 		return 0;
   278 	}
   279 
   280 	index = SDLTest_RandomSint32() % size;
   281 	retVal = (Uint8)buffer[index];
   282 
   283 	SDL_free(buffer);
   284 
   285 	fuzzerInvocationCounter++;
   286 
   287 	return retVal;
   288 }
   289 
   290 Uint16
   291 SDLTest_RandomUint16BoundaryValue(Uint16 boundary1, Uint16 boundary2, SDL_bool validDomain)
   292 {
   293 	Uint64 *buffer = NULL;
   294 	Uint32 size;
   295 	Uint32 index;
   296 	Uint16 retVal;
   297 
   298 	// max value for Uint16
   299 	const Uint64 maxValue = UINT16_MAX;
   300 
   301 	size = SDLTest_GenerateUnsignedBoundaryValues(maxValue,
   302 				(Uint64) boundary1, (Uint64) boundary2,
   303 				validDomain, buffer);
   304 	if (buffer == NULL || size == 0) {
   305 		return 0;
   306 	}
   307 
   308 	index = SDLTest_RandomSint32() % size;
   309 	retVal = (Uint16) buffer[index];
   310 
   311 	SDL_free(buffer);
   312 
   313 	fuzzerInvocationCounter++;
   314 
   315 	return retVal;
   316 }
   317 
   318 Uint32
   319 SDLTest_RandomUint32BoundaryValue(Uint32 boundary1, Uint32 boundary2, SDL_bool validDomain)
   320 {
   321 	Uint64 *buffer = NULL;
   322 	Uint32 size;
   323 	Uint32 index;
   324 	Uint32 retVal;
   325 
   326 	// max value for Uint32
   327 	const Uint64 maxValue = UINT32_MAX;
   328 
   329 	size = SDLTest_GenerateUnsignedBoundaryValues(maxValue,
   330 				(Uint64) boundary1, (Uint64) boundary2,
   331 				validDomain, buffer);
   332 	if (buffer == NULL || size == 0) {
   333 		return 0;
   334 	}
   335 
   336 	index = SDLTest_RandomSint32() % size;
   337 	retVal = (Uint32) buffer[index];
   338 
   339 	SDL_free(buffer);
   340 
   341 	fuzzerInvocationCounter++;
   342 
   343 	return retVal;
   344 }
   345 
   346 Uint64
   347 SDLTest_RandomUint64BoundaryValue(Uint64 boundary1, Uint64 boundary2, SDL_bool validDomain)
   348 {
   349 	Uint64 *buffer = NULL;
   350 	Uint32 size;
   351 	Uint32 index;
   352 	Uint64 retVal;
   353 
   354 	// max value for Uint64
   355 	const Uint64 maxValue = UINT64_MAX;
   356 
   357 	size = SDLTest_GenerateUnsignedBoundaryValues(maxValue,
   358 				(Uint64) boundary1, (Uint64) boundary2,
   359 				validDomain, buffer);
   360 	if (buffer == NULL || size == 0) {
   361 		return 0;
   362 	}
   363 
   364 	index = SDLTest_RandomSint32() % size;
   365 	retVal = (Uint64) buffer[index];
   366 
   367 	SDL_free(buffer);
   368 
   369 	fuzzerInvocationCounter++;
   370 
   371 	return retVal;
   372 }
   373 
   374 /*!
   375  * Generates boundary values between the given boundaries.
   376  * Boundary values are inclusive. See the examples below.
   377  * If boundary2 < boundary1, the values are swapped.
   378  * If boundary1 == boundary2, value of boundary1 will be returned
   379  *
   380  * Generating boundary values for Sint8:
   381  * SignedBoundaryValues(sizeof(Sint8), -10, 20, True) -> [-11,-10,19,20]
   382  * SignedBoundaryValues(sizeof(Sint8), -10, 20, False) -> [-11,21]
   383  * SignedBoundaryValues(sizeof(Sint8), -30, -15, True) -> [-30, -29, -16, -15]
   384  * SignedBoundaryValues(sizeof(Sint8), -128, 15, False) -> [16]
   385  * SignedBoundaryValues(sizeof(Sint8), -128, 127, False) -> NULL
   386  *
   387  * Generator works the same for other types of signed integers.
   388  *
   389  * Note: outBuffer will be allocated and needs to be freed later.
   390  * If outbuffer != NULL, it'll be freed.
   391  *
   392  *
   393  * \param minValue The smallest value  that is acceptable for this data type.
   394  *					For instance, for Uint8 -> -128, Uint16 -> -32,768 etc.
   395  * \param maxValue The biggest value that is acceptable for this data type.
   396  * 					For instance, for Uint8 -> 127, Uint16 -> 32767 etc.
   397  * \param pBoundary1 defines lower boundary
   398  * \param pBoundary2 defines upper boundary
   399  * \param validDomain Generate only for valid domain (for the data type)
   400  *
   401  * \param outBuffer The generated boundary values are put here
   402  *
   403  * \returns Returns the number of elements in outBuffer or -1 in case of error
   404  */
   405 Uint32
   406 SDLTest_GenerateSignedBoundaryValues(const Sint64 minValue, const Sint64 maxValue,
   407 					Sint64 pBoundary1, Sint64 pBoundary2, SDL_bool validDomain,
   408 					Sint64 *outBuffer)
   409 {
   410 	int index;
   411 	Sint64 tempBuf[4];
   412 	Sint64 boundary1 = pBoundary1, boundary2 = pBoundary2;
   413 
   414 	if(outBuffer != NULL) {
   415 		SDL_free(outBuffer);
   416 	}
   417 
   418 	if(boundary1 > boundary2) {
   419 		Sint64 temp = boundary1;
   420 		boundary1 = boundary2;
   421 		boundary2 = temp;
   422 	}
   423 
   424 	index = 0;
   425 	if(boundary1 == boundary2) {
   426 		tempBuf[index++] = boundary1;
   427 	}
   428 	else if(validDomain) {
   429 		tempBuf[index++] = boundary1;
   430 
   431 		if(boundary1 < LLONG_MAX)
   432 			tempBuf[index++] = boundary1 + 1;
   433 
   434 		if(boundary2 > LLONG_MIN)
   435 			tempBuf[index++] = boundary2 - 1;
   436 
   437 		tempBuf[index++] = boundary2;
   438 	}
   439 	else {
   440 		if(boundary1 > minValue &&  boundary1 > LLONG_MIN) {
   441 			tempBuf[index++] = boundary1 - 1;
   442 		}
   443 
   444 		if(boundary2 < maxValue && boundary2 < UINT64_MAX) {
   445 			tempBuf[index++] = boundary2 + 1;
   446 		}
   447 	}
   448 
   449 	if(index == 0) {
   450 		// There are no valid boundaries
   451 		return 0;
   452 	}
   453 
   454 	// Create the return buffer
   455 	outBuffer = (Sint64 *)SDL_malloc(index * sizeof(Sint64));
   456 	if(outBuffer == NULL) {
   457 		return 0;
   458 	}
   459 
   460 	SDL_memcpy((void *)outBuffer, (void *)tempBuf, index * sizeof(Sint64));
   461 
   462 	return (Uint32)index;
   463 }
   464 
   465 Sint8
   466 SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, SDL_bool validDomain)
   467 {
   468 	// min & max values for Sint8
   469 	const Sint64 maxValue = CHAR_MAX;
   470 	const Sint64 minValue = CHAR_MIN;
   471 
   472 	Sint64 *buffer = NULL;
   473 	Uint32 size;
   474 	Uint32 index;
   475 	Sint8 retVal;
   476 
   477 	size = SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   478 				(Sint64) boundary1, (Sint64) boundary2,
   479 				validDomain, buffer);
   480 	if (buffer == NULL || size == 0) {
   481 		return CHAR_MIN;
   482 	}
   483 
   484 	index = SDLTest_RandomSint32() % size;
   485 	retVal = (Sint8) buffer[index];
   486 
   487 	SDL_free(buffer);
   488 
   489 	fuzzerInvocationCounter++;
   490 
   491 	return retVal;
   492 }
   493 
   494 Sint16
   495 SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, SDL_bool validDomain)
   496 {
   497 	// min & max values for Sint16
   498 	const Sint64 maxValue = SHRT_MAX;
   499 	const Sint64 minValue = SHRT_MIN;
   500 	Sint64 *buffer = NULL;
   501 	Uint32 size;
   502 	Uint32 index;
   503 	Sint16 retVal;
   504 
   505 	size = SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   506 					(Sint64) boundary1, (Sint64) boundary2,
   507 					validDomain, buffer);
   508 	if (buffer == NULL || size == 0) {
   509 		return SHRT_MIN;
   510 	}
   511 
   512 	index = SDLTest_RandomSint32() % size;
   513 	retVal = (Sint16) buffer[index];
   514 
   515 	SDL_free(buffer);
   516 
   517 	fuzzerInvocationCounter++;
   518 
   519 	return retVal;
   520 }
   521 
   522 Sint32
   523 SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, SDL_bool validDomain)
   524 {
   525 	// min & max values for Sint32
   526 	const Sint64 maxValue = INT_MAX;
   527 	const Sint64 minValue = INT_MIN;
   528 
   529 	Sint64 *buffer = NULL;
   530 	Uint32 size;
   531 	Uint32 index;
   532 	Sint32 retVal;
   533 
   534 	size = SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   535 				(Sint64) boundary1, (Sint64) boundary2,
   536 				validDomain, buffer);
   537 	if (buffer == NULL || size == 0) {
   538 		return INT_MIN;
   539 	}
   540 
   541 	index = SDLTest_RandomSint32() % size;
   542 	retVal = (Sint32) buffer[index];
   543 
   544 	SDL_free(buffer);
   545 
   546 	fuzzerInvocationCounter++;
   547 
   548 	return retVal;
   549 }
   550 
   551 Sint64
   552 SDLTest_RandomSint64BoundaryValue(Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain)
   553 {
   554 	Sint64 *buffer = NULL;
   555 	Uint32 size;
   556 	Uint32 index;
   557 	Sint64 retVal;
   558 
   559 	// min & max values for Sint64
   560 	const Sint64 maxValue = LLONG_MAX;
   561 	const Sint64 minValue = LLONG_MIN;
   562 
   563 	size = SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   564 				(Sint64) boundary1, (Sint64) boundary2,
   565 				validDomain, buffer);
   566 	if (buffer == NULL || size == 0) {
   567 		return LLONG_MIN;
   568 	}
   569 
   570 	index = SDLTest_RandomSint32() % size;
   571 	retVal = (Sint64) buffer[index];
   572 
   573 	SDL_free(buffer);
   574 
   575 	fuzzerInvocationCounter++;
   576 
   577 	return retVal;
   578 }
   579 
   580 float
   581 SDLTest_RandomUnitFloat()
   582 {
   583 	return (float) SDLTest_RandomUint32() / UINT_MAX;
   584 }
   585 
   586 float
   587 SDLTest_RandomFloat()
   588 {
   589         return (float) (FLT_MIN + SDLTest_RandomUnitDouble() * (FLT_MAX - FLT_MIN));
   590 }
   591 
   592 double
   593 SDLTest_RandomUnitDouble()
   594 {
   595 	return (double) (SDLTest_RandomUint64() >> 11) * (1.0/9007199254740992.0);
   596 }
   597 
   598 double
   599 SDLTest_RandomDouble()
   600 {
   601 	double r = 0.0;
   602 	double s = 1.0;
   603 	do {
   604 	  s /= UINT_MAX + 1.0;
   605 	  r += (double)SDLTest_RandomInt(&rndContext) * s;
   606 	} while (s > DBL_EPSILON);
   607 	  
   608 	fuzzerInvocationCounter++;
   609 	
   610 	return r;
   611 }
   612 
   613 
   614 char *
   615 SDLTest_RandomAsciiString()
   616 {
   617 	return SDLTest_RandomAsciiStringWithMaximumLength(255);
   618 }
   619 
   620 char *
   621 SDLTest_RandomAsciiStringWithMaximumLength(int maxLength)
   622 {
   623 	int size;
   624 
   625 	if(maxLength < 1) {
   626                 SDL_InvalidParamError("maxLength");
   627 		return NULL;
   628 	}
   629 
   630 	size = (SDLTest_RandomUint32() % (maxLength + 1));
   631 	
   632 	return SDLTest_RandomAsciiStringOfSize(size);	
   633 }
   634 
   635 char *
   636 SDLTest_RandomAsciiStringOfSize(int size)
   637 {
   638 	char *string;
   639 	int counter;
   640 
   641 
   642 	if(size < 1) {
   643                 SDL_InvalidParamError("size");
   644 		return NULL;
   645 	}
   646 
   647 	string = (char *)SDL_malloc((size + 1) * sizeof(char));
   648 	if (string==NULL) {
   649 	  return NULL;
   650         }
   651 
   652 	for(counter = 0; counter < size; ++counter) {
   653 		string[counter] = (char)SDLTest_RandomIntegerInRange(32, 126);
   654 	}
   655 
   656 	string[counter] = '\0';
   657 
   658 	fuzzerInvocationCounter++;
   659 
   660 	return string;
   661 }