|
@@ -121,6 +121,7 @@ typedef enum {
|
|
|
OP_VALIDATE = 5, // Validate examples, using [examples_list.txt] as main source by default
|
|
OP_VALIDATE = 5, // Validate examples, using [examples_list.txt] as main source by default
|
|
|
OP_UPDATE = 6, // Validate and update required examples (as far as possible)
|
|
OP_UPDATE = 6, // Validate and update required examples (as far as possible)
|
|
|
OP_BUILD = 7, // Build example for desktop and web, copy web output
|
|
OP_BUILD = 7, // Build example for desktop and web, copy web output
|
|
|
|
|
+ OP_TEST = 8, // Test example: check output LOG WARNINGS
|
|
|
} rlExampleOperation;
|
|
} rlExampleOperation;
|
|
|
|
|
|
|
|
static const char *exCategories[REXM_MAX_EXAMPLE_CATEGORIES] = { "core", "shapes", "textures", "text", "models", "shaders", "audio", "others" };
|
|
static const char *exCategories[REXM_MAX_EXAMPLE_CATEGORIES] = { "core", "shapes", "textures", "text", "models", "shaders", "audio", "others" };
|
|
@@ -413,6 +414,36 @@ int main(int argc, char *argv[])
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ else if (strcmp(argv[1], "test") == 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Build and test example for PLATFORM_DESKTOP
|
|
|
|
|
+ // NOTE: Build outputs to default directory, usually where the .c file is located,
|
|
|
|
|
+ // to avoid issues with copying resources (at least on Desktop)
|
|
|
|
|
+ if (argc == 2) LOG("WARNING: No example name provided to test\n");
|
|
|
|
|
+ else if (argc > 3) LOG("WARNING: Too many arguments provided\n");
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ // Support building not only individual examples but categories and "ALL"
|
|
|
|
|
+ if ((strcmp(argv[2], "ALL") == 0) || TextInList(argv[2], exCategories, REXM_MAX_EXAMPLE_CATEGORIES))
|
|
|
|
|
+ {
|
|
|
|
|
+ // Category/ALL rebuilt requested
|
|
|
|
|
+ strcpy(exRebuildRequested, argv[2]);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ // Verify example exists in collection to be removed
|
|
|
|
|
+ char *exColInfo = LoadFileText(exCollectionFilePath);
|
|
|
|
|
+ if (TextFindIndex(exColInfo, argv[2]) != -1) // Example in the collection
|
|
|
|
|
+ {
|
|
|
|
|
+ strcpy(exName, argv[2]); // Register example name
|
|
|
|
|
+ strncpy(exCategory, exName, TextFindIndex(exName, "_"));
|
|
|
|
|
+ opCode = OP_TEST;
|
|
|
|
|
+ }
|
|
|
|
|
+ else LOG("WARNING: TEST: Example requested not available in the collection\n");
|
|
|
|
|
+ UnloadFileText(exColInfo);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// Process command line options arguments
|
|
// Process command line options arguments
|
|
|
for (int i = 1; i < argc; i++)
|
|
for (int i = 1; i < argc; i++)
|
|
@@ -1487,6 +1518,94 @@ int main(int argc, char *argv[])
|
|
|
UnloadExamplesData(exCollection);
|
|
UnloadExamplesData(exCollection);
|
|
|
//------------------------------------------------------------------------------------------------
|
|
//------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
+ } break;
|
|
|
|
|
+ case OP_TEST:
|
|
|
|
|
+ {
|
|
|
|
|
+ LOG("INFO: Command requested: TEST\n");
|
|
|
|
|
+ LOG("INFO: Example to be built and tested: %s\n", exName);
|
|
|
|
|
+
|
|
|
|
|
+ // Steps to follow
|
|
|
|
|
+ // STEP 1: Load example.c and replace required code to inject basic testing code: frames to run
|
|
|
|
|
+ // OPTION 1: Code injection required multiple changes for testing but it does not require raylib changes!
|
|
|
|
|
+ // OPTION 2: Support testing on raylib side: Args processing and events injection: SUPPORT_AUTOMATD_TESTING_SYSTEM, EVENTS_TESTING_MODE
|
|
|
|
|
+ // STEP 2: Build example (PLATFORM_DESKTOP)
|
|
|
|
|
+ // STEP 3: Run example with arguments: --frames 2 > <example>.out.log
|
|
|
|
|
+ // STEP 4: Load <example>.out.log and check "WARNING:" messages -> Some could maybe be ignored
|
|
|
|
|
+ // STEP 5: Generate report with results
|
|
|
|
|
+
|
|
|
|
|
+ // STEP 1: Load example and inject required code
|
|
|
|
|
+ // PROBLEM: As we need to modify the example source code for building, we need to keep a copy or something
|
|
|
|
|
+ // WARNING: If we make a copy and something fails, it could not be restored at the end
|
|
|
|
|
+ // PROBLEM: Trying to build a copy won't work because Makefile is setup to look for specific example on specific path -> No output dir config
|
|
|
|
|
+ // IDEA: Create directory for testing data -> It implies moving files and set working dir...
|
|
|
|
|
+ // SOLUTION: Make a copy of original file -> Modify original -> Build -> Rename to <example>.test.exe
|
|
|
|
|
+ FileCopy(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName),
|
|
|
|
|
+ TextFormat("%s/%s/%s.original.c", exBasePath, exCategory, exName));
|
|
|
|
|
+ char *srcText = LoadFileText(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName));
|
|
|
|
|
+
|
|
|
|
|
+ static const char *mainReplaceText =
|
|
|
|
|
+ "#include <string.h>\n"
|
|
|
|
|
+ "#include <stdlib.h>\n"
|
|
|
|
|
+ "int main(int argc, char *argv[])\n{\n"
|
|
|
|
|
+ " int requestedTestFrames = 0;\n"
|
|
|
|
|
+ " int testFramesCount = 0;\n"
|
|
|
|
|
+ " if ((argc > 1) && (argc == 3) && (strcmp(argv[1], \"--frames\") != 0)) requestedTestFrames = atoi(argv[2]);\n";
|
|
|
|
|
+
|
|
|
|
|
+ char *srcTextUpdated[3] = { 0 };
|
|
|
|
|
+ srcTextUpdated[0] = TextReplace(srcText, "int main(void)\n{", mainReplaceText);
|
|
|
|
|
+ srcTextUpdated[1] = TextReplace(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)");
|
|
|
|
|
+ srcTextUpdated[2] = TextReplace(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;");
|
|
|
|
|
+ UnloadFileText(srcText);
|
|
|
|
|
+
|
|
|
|
|
+ SaveFileText(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), srcTextUpdated[2]);
|
|
|
|
|
+ for (int i = 0; i < 3; i++) { MemFree(srcTextUpdated[i]); srcTextUpdated[i] = NULL; }
|
|
|
|
|
+
|
|
|
|
|
+ // STEP 2: Build example for DESKTOP platform
|
|
|
|
|
+#if defined(_WIN32)
|
|
|
|
|
+ // Set required environment variables
|
|
|
|
|
+ //putenv(TextFormat("RAYLIB_DIR=%s\\..", exBasePath));
|
|
|
|
|
+ _putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin");
|
|
|
|
|
+ //putenv("MAKE=mingw32-make");
|
|
|
|
|
+ //ChangeDirectory(exBasePath);
|
|
|
|
|
+#endif
|
|
|
|
|
+ // Build example for PLATFORM_DESKTOP
|
|
|
|
|
+#if defined(_WIN32)
|
|
|
|
|
+ LOG("INFO: [%s] Building example for PLATFORM_DESKTOP (Host: Win32)\n", exName);
|
|
|
|
|
+ system(TextFormat("mingw32-make -C %s %s/%s PLATFORM=PLATFORM_DESKTOP -B", exBasePath, exCategory, exName));
|
|
|
|
|
+#else
|
|
|
|
|
+ LOG("INFO: [%s] Building example for PLATFORM_DESKTOP (Host: POSIX)\n", exName);
|
|
|
|
|
+ system(TextFormat("make -C %s %s/%s PLATFORM=PLATFORM_DESKTOP -B", exBasePath, exCategory, exName));
|
|
|
|
|
+#endif
|
|
|
|
|
+ // Restore original source code before continue
|
|
|
|
|
+ FileCopy(TextFormat("%s/%s/%s.original.c", exBasePath, exCategory, exName),
|
|
|
|
|
+ TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName));
|
|
|
|
|
+ FileRemove(TextFormat("%s/%s/%s.original.c", exBasePath, exCategory, exName));
|
|
|
|
|
+
|
|
|
|
|
+ // STEP 3: Run example with required arguments
|
|
|
|
|
+ ChangeDirectory(TextFormat("%s/%s", exBasePath, exCategory));
|
|
|
|
|
+ system(TextFormat("%s --frames 2 > %s.log", exName, exName));
|
|
|
|
|
+
|
|
|
|
|
+ // STEP 4: Load and validate log -> WARNINGS
|
|
|
|
|
+ char *exTestLog = LoadFileText(TextFormat("%s/%s/%s.log", exBasePath, exCategory, exName));
|
|
|
|
|
+ int exTestLogLinesCount = 0;
|
|
|
|
|
+ char **exTestLogLines = LoadTextLines(exTestLog, &exTestLogLinesCount);
|
|
|
|
|
+ UnloadFileText(exTestLog);
|
|
|
|
|
+
|
|
|
|
|
+ int issueCounter = false;
|
|
|
|
|
+ for (int i = 0; i < exTestLogLinesCount; i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (TextFindIndex(exTestLogLines[i], "WARNING") >= 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ LOG("TEST: [%s] %s\n", exName, exTestLogLines[i]);
|
|
|
|
|
+ issueCounter++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ UnloadTextLines(exTestLogLines, exTestLogLinesCount);
|
|
|
|
|
+
|
|
|
|
|
+ // STEP 5: Generate auto-test report
|
|
|
|
|
+ //if (issueCounter > 0)
|
|
|
|
|
+
|
|
|
} break;
|
|
} break;
|
|
|
default: // Help
|
|
default: // Help
|
|
|
{
|
|
{
|