mirror of
https://github.com/bulletphysics/bullet3
synced 2025-01-07 08:10:08 +00:00
ab8f16961e
Apply clang-format-all.sh using the _clang-format file through all the cpp/.h files. make sure not to apply it to certain serialization structures, since some parser expects the * as part of the name, instead of type. This commit contains no other changes aside from adding and applying clang-format-all.sh
321 lines
6.7 KiB
C++
321 lines
6.7 KiB
C++
//
|
|
// main.c
|
|
// BulletTest
|
|
//
|
|
// Copyright (c) 2011 Apple Inc.
|
|
//
|
|
#include <stdio.h>
|
|
#ifdef __APPLE__
|
|
#include <libgen.h>
|
|
#endif //__APPLE__
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <limits.h>
|
|
#include "main.h"
|
|
#include "Utils.h"
|
|
#include "TestList.h"
|
|
#include "LinearMath/btScalar.h"
|
|
|
|
#if defined(BT_USE_NEON) || defined(BT_USE_SSE_IN_API)
|
|
|
|
#ifdef _WIN32
|
|
#define strcasecmp _stricmp
|
|
#define basename(A) A
|
|
#endif
|
|
|
|
#define EXIT_NO_ERROR INT_MIN
|
|
|
|
//int gReportNanoseconds = 0; // in Utils.c
|
|
|
|
int gReportAverageTimes = 0;
|
|
int gExitOnError = 0;
|
|
char *gFullPath = NULL;
|
|
const char *gAppName = NULL;
|
|
int gArgc;
|
|
const char **gArgv;
|
|
|
|
typedef struct TestNode
|
|
{
|
|
struct TestNode *next;
|
|
const char *name;
|
|
} TestNode;
|
|
|
|
TestNode *gNodeList = NULL;
|
|
|
|
static int ParseArgs(int argc, const char *argv[]);
|
|
static void PrintUsage(void);
|
|
static int Init(void);
|
|
static void ListTests(void);
|
|
|
|
const char *gArch =
|
|
#ifdef __i386__
|
|
"i386";
|
|
#elif defined __x86_64__
|
|
"x86_64";
|
|
#elif defined __arm__
|
|
"arm";
|
|
#elif defined _WIN64
|
|
"win64";
|
|
#elif defined _WIN32
|
|
"win32";
|
|
#else
|
|
#error unknown arch
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
|
|
int main(int argc, const char *argv[])
|
|
{
|
|
// Enable just one test programatically (instead of command-line param)
|
|
// TestNode *node = (TestNode*) malloc( sizeof( TestNode ) );
|
|
// node->name = "btDbvt";
|
|
// node->next = 0;
|
|
// gNodeList = node;
|
|
|
|
srand(0.f);
|
|
|
|
int numPassedTests = 0;
|
|
int numFailedTests = 0;
|
|
|
|
int err;
|
|
|
|
// Parse arguments. Build gNodeList.
|
|
if ((err = ParseArgs(argc, argv)))
|
|
{
|
|
if (EXIT_NO_ERROR == err)
|
|
return 0;
|
|
|
|
PrintUsage();
|
|
return err;
|
|
}
|
|
|
|
printf("Arch: %s\n", gArch);
|
|
|
|
if (gReportAverageTimes)
|
|
printf("Reporting average times.\n");
|
|
else
|
|
printf("Reporting best times.\n");
|
|
|
|
// Set a few things up
|
|
if ((err = Init()))
|
|
{
|
|
printf("Init failed.\n");
|
|
return err;
|
|
}
|
|
|
|
if (NULL == gNodeList)
|
|
{ // test everything
|
|
printf("No function list found. Testing everything...\n");
|
|
size_t i;
|
|
for (i = 0; NULL != gTestList[i].test_func; i++)
|
|
{
|
|
printf("\n----------------------------------------------\n");
|
|
printf("Testing %s:\n", gTestList[i].name);
|
|
printf("----------------------------------------------\n");
|
|
uint64_t startTime = ReadTicks();
|
|
int local_error = gTestList[i].test_func();
|
|
uint64_t currentTime = ReadTicks() - startTime;
|
|
if (local_error)
|
|
{
|
|
numFailedTests++;
|
|
printf("*** %s test failed with error: %d\n", gTestList[i].name, local_error);
|
|
if (gExitOnError)
|
|
return local_error;
|
|
if (0 == err)
|
|
err = local_error;
|
|
}
|
|
else
|
|
{
|
|
numPassedTests++;
|
|
printf("%s Passed.\t\t\t(%2.2gs)\n", gTestList[i].name, TicksToSeconds(currentTime));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{ // test just the list
|
|
while (NULL != gNodeList)
|
|
{
|
|
TestNode *currentNode = gNodeList;
|
|
gNodeList = gNodeList->next;
|
|
|
|
// Find the test with that name
|
|
size_t i;
|
|
for (i = 0; NULL != gTestList[i].test_func; i++)
|
|
if (0 == strcasecmp(currentNode->name, gTestList[i].name))
|
|
break;
|
|
|
|
if (NULL != gTestList[i].test_func)
|
|
{
|
|
printf("\n----------------------------------------------\n");
|
|
printf("Testing %s:\n", gTestList[i].name);
|
|
printf("----------------------------------------------\n");
|
|
uint64_t startTime = ReadTicks();
|
|
int local_error = gTestList[i].test_func();
|
|
uint64_t currentTime = ReadTicks() - startTime;
|
|
if (local_error)
|
|
{
|
|
numFailedTests++;
|
|
printf("*** %s test failed with error: %d\n", gTestList[i].name, local_error);
|
|
if (gExitOnError)
|
|
return local_error;
|
|
if (0 == err)
|
|
err = local_error;
|
|
}
|
|
else
|
|
{
|
|
numPassedTests++;
|
|
printf("%s Passed.\t\t\t(%2.2gs)\n", gTestList[i].name, TicksToSeconds(currentTime));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("\n***Error: Test name \"%s\" not found! Skipping.\n", currentNode->name);
|
|
err = -1;
|
|
if (gExitOnError)
|
|
return -1;
|
|
}
|
|
|
|
free(currentNode);
|
|
}
|
|
}
|
|
printf("\n----------------------------------------------\n");
|
|
printf("numPassedTests = %d, numFailedTests = %d\n", numPassedTests, numFailedTests);
|
|
|
|
free(gFullPath);
|
|
return err;
|
|
}
|
|
|
|
static int Init(void)
|
|
{
|
|
// init the timer
|
|
TicksToCycles(0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int ParseArgs(int argc, const char *argv[])
|
|
{
|
|
int listTests = 0;
|
|
TestNode *list = NULL;
|
|
|
|
gArgc = argc;
|
|
gArgv = argv;
|
|
gFullPath = (char *)malloc(strlen(argv[0]) + 1);
|
|
strcpy(gFullPath, argv[0]);
|
|
gAppName = basename(gFullPath);
|
|
if (NULL == gAppName)
|
|
gAppName = "<unknown app name>";
|
|
|
|
printf("%s ", gAppName);
|
|
int skipremaining = 0;
|
|
|
|
size_t i;
|
|
for (i = 1; i < argc; i++)
|
|
{
|
|
const char *arg = argv[i];
|
|
printf("\t%s", arg);
|
|
if (arg[0] == '-')
|
|
{
|
|
arg++;
|
|
while (arg[0] != '\0')
|
|
{
|
|
int stop = 0;
|
|
switch (arg[0])
|
|
{
|
|
case 'a':
|
|
gReportAverageTimes ^= 1;
|
|
break;
|
|
case 'e':
|
|
gExitOnError ^= 1;
|
|
break;
|
|
case 'h':
|
|
PrintUsage();
|
|
return EXIT_NO_ERROR;
|
|
case 'l':
|
|
listTests ^= 1;
|
|
return EXIT_NO_ERROR;
|
|
case 's':
|
|
gReportNanoseconds ^= 1;
|
|
break;
|
|
case ' ':
|
|
stop = 1;
|
|
break;
|
|
case 'N': //ignore the -NSDocumentRevisionsDebugMode argument from XCode 4.3.2
|
|
skipremaining = 1;
|
|
stop = 1;
|
|
break;
|
|
default:
|
|
printf("\nError: Unknown flag \'%c\'\n", arg[0]);
|
|
return -1;
|
|
}
|
|
if (stop)
|
|
break;
|
|
arg++;
|
|
}
|
|
}
|
|
else
|
|
{ // add function name to the list
|
|
TestNode *node = (TestNode *)malloc(sizeof(TestNode));
|
|
node->name = arg;
|
|
node->next = list;
|
|
list = node;
|
|
}
|
|
if (skipremaining)
|
|
break;
|
|
}
|
|
|
|
// reverse the list of test names, and stick on gNodeList
|
|
while (list)
|
|
{
|
|
TestNode *node = list;
|
|
TestNode *next = node->next;
|
|
node->next = gNodeList;
|
|
gNodeList = node;
|
|
list = next;
|
|
}
|
|
|
|
printf("\n");
|
|
if (listTests)
|
|
ListTests();
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void PrintUsage(void)
|
|
{
|
|
printf("\nUsage:\n");
|
|
printf("%s: <-aehls> <test names>", gAppName);
|
|
printf("Options:\n");
|
|
printf("\t-a\tToggle report average times vs. best times. (Default: best times)\n");
|
|
printf("\t-e\tToggle exit immediately on error behavior. (Default: off)\n");
|
|
printf("\t-h\tPrint this message.\n");
|
|
printf("\t-l\tToggle list available test names. (Default: off)\n");
|
|
printf("\t-s\tToggle report times in cycles or nanoseconds. (Default: cycles)\n\n");
|
|
printf("\tOptions may be followed by one or more test names. If no test names \n");
|
|
printf("\tare provided, then all tests are run.\n\n");
|
|
}
|
|
|
|
static void ListTests(void)
|
|
{
|
|
size_t i;
|
|
|
|
printf("\nTests:\n");
|
|
for (i = 0; NULL != gTestList[i].test_func; i++)
|
|
{
|
|
printf("%19s", gTestList[i].name);
|
|
if (NULL != gTestList[i].test_func)
|
|
printf(",");
|
|
if (3 == (i & 3))
|
|
printf("\n");
|
|
}
|
|
}
|
|
#else
|
|
#include <stdio.h>
|
|
int main(int argc, char* argv[])
|
|
{
|
|
printf("error: no SIMD enabled through BT_USE_NEON or BT_USE_SSE_IN_API \n(enable in LinearMath/btScalar.h or through build system)\n");
|
|
return 0;
|
|
}
|
|
#endif
|