CREATE_PROJECT: Add support for tests

- Added --tests command line switch
 - Parse test/module.mk to extract the list of test folders
 - Automatically run tests after a successful build
This commit is contained in:
Littleboy 2013-07-07 11:23:19 -04:00
parent 98899c6ce3
commit a949a88220
12 changed files with 262 additions and 78 deletions

View file

@ -109,7 +109,7 @@ enum ProjectType {
int main(int argc, char *argv[]) {
#ifndef USE_WIN32_API
// Initialize random number generator for UUID creation
std::srand((uint)std::time(0));
std::srand((unsigned int)std::time(0));
#endif
if (argc < 2) {
@ -264,7 +264,7 @@ int main(int argc, char *argv[]) {
setup.filePrefix.erase(setup.filePrefix.size() - 1);
} else if (!std::strcmp(argv[i], "--output-dir")) {
if (i + 1 >= argc) {
std::cerr << "ERROR: Missing \"path\" parameter for \"--output-dirx\"!\n";
std::cerr << "ERROR: Missing \"path\" parameter for \"--output-dir\"!\n";
return -1;
}
@ -279,12 +279,23 @@ int main(int argc, char *argv[]) {
setup.createInstaller = true;
} else if (!std::strcmp(argv[i], "--tools")) {
setup.devTools = true;
} else if (!std::strcmp(argv[i], "--tests")) {
setup.tests = true;
} else {
std::cerr << "ERROR: Unknown parameter \"" << argv[i] << "\"\n";
return -1;
}
}
// When building tests, disable some features
if (setup.tests) {
setFeatureBuildState("mt32emu", setup.features, false);
setFeatureBuildState("eventrecorder", setup.features, false);
for (EngineDescList::iterator j = setup.engines.begin(); j != setup.engines.end(); ++j)
j->enable = false;
}
// Print status
cout << "Enabled engines:\n\n";
for (EngineDescList::const_iterator i = setup.engines.begin(); i != setup.engines.end(); ++i) {
@ -321,6 +332,12 @@ int main(int argc, char *argv[]) {
}
}
// Check if tools and tests are enabled simultaneously
if (setup.devTools && setup.tests) {
std::cerr << "ERROR: The tools and tests projects cannot be created simultaneously\n";
return -1;
}
// Setup defines and libraries
setup.defines = getEngineDefines(setup.engines);
setup.libraries = getFeatureLibraries(setup.features);
@ -358,8 +375,8 @@ int main(int argc, char *argv[]) {
return -1;
case kProjectCodeBlocks:
if (setup.devTools) {
std::cerr << "ERROR: Building tools is not supported for the CodeBlocks project type!\n";
if (setup.devTools || setup.tests) {
std::cerr << "ERROR: Building tools or tests is not supported for the CodeBlocks project type!\n";
return -1;
}
@ -531,8 +548,8 @@ int main(int argc, char *argv[]) {
break;
case kProjectXcode:
if (setup.devTools) {
std::cerr << "ERROR: Building tools is not supported for the XCode project type!\n";
if (setup.devTools || setup.tests) {
std::cerr << "ERROR: Building tools or tests is not supported for the XCode project type!\n";
return -1;
}
@ -573,6 +590,11 @@ int main(int argc, char *argv[]) {
setup.projectDescription += "Tools";
}
if (setup.tests) {
setup.projectName += "-tests";
setup.projectDescription += "Tests";
}
provider->createProject(setup);
delete provider;
@ -623,6 +645,9 @@ void displayHelp(const char *exe) {
" --tools Create project files for the devtools\n"
" (ignores --build-events and --installer, as well as engine settings)\n"
" (default: false)\n"
" --tests Create project files for the tests\n"
" (ignores --build-events and --installer, as well as engine settings)\n"
" (default: false)\n"
"\n"
"Engines settings:\n"
" --list-engines list all available engines and their default state\n"
@ -1130,69 +1155,66 @@ ProjectProvider::ProjectProvider(StringList &global_warnings, std::map<std::stri
: _version(version), _globalWarnings(global_warnings), _projectWarnings(project_warnings) {
}
void ProjectProvider::createProject(const BuildSetup &setup) {
void ProjectProvider::createProject(BuildSetup &setup) {
std::string targetFolder;
if (setup.devTools) {
_uuidMap = createToolsUUIDMap();
// We also need to add the UUID of the main project file.
const std::string svmUUID = _uuidMap[setup.projectName] = createUUID();
createWorkspace(setup);
StringList in, ex;
// Create tools project files
for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) {
if (i->first == setup.projectName)
continue;
in.clear(); ex.clear();
const std::string moduleDir = setup.srcDir + "/devtools/" + i->first;
createModuleList(moduleDir, setup.defines, in, ex);
createProjectFile(i->first, i->second, setup, moduleDir, in, ex);
}
// Create other misc. build files
createOtherBuildFiles(setup);
} else {
targetFolder = "/devtools/";
} else if (!setup.tests) {
_uuidMap = createUUIDMap(setup);
targetFolder = "/engines/";
}
// We also need to add the UUID of the main project file.
const std::string svmUUID = _uuidMap[setup.projectName] = createUUID();
// We also need to add the UUID of the main project file.
const std::string svmUUID = _uuidMap[setup.projectName] = createUUID();
// Create Solution/Workspace file
createWorkspace(setup);
createWorkspace(setup);
StringList in, ex;
StringList in, ex;
// Create engine project files
for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) {
if (i->first == setup.projectName)
continue;
// Create project files
for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) {
if (i->first == setup.projectName)
continue;
in.clear(); ex.clear();
const std::string moduleDir = setup.srcDir + "/engines/" + i->first;
in.clear(); ex.clear();
const std::string moduleDir = setup.srcDir + targetFolder + i->first;
createModuleList(moduleDir, setup.defines, in, ex);
createProjectFile(i->first, i->second, setup, moduleDir, in, ex);
}
createModuleList(moduleDir, setup.defines, setup.testDirs, in, ex);
createProjectFile(i->first, i->second, setup, moduleDir, in, ex);
}
if (setup.tests) {
// Create the main project file.
in.clear(); ex.clear();
createModuleList(setup.srcDir + "/backends", setup.defines, setup.testDirs, in, ex);
createModuleList(setup.srcDir + "/backends/platform/sdl", setup.defines, setup.testDirs, in, ex);
createModuleList(setup.srcDir + "/base", setup.defines, setup.testDirs, in, ex);
createModuleList(setup.srcDir + "/common", setup.defines, setup.testDirs, in, ex);
createModuleList(setup.srcDir + "/engines", setup.defines, setup.testDirs, in, ex);
createModuleList(setup.srcDir + "/graphics", setup.defines, setup.testDirs, in, ex);
createModuleList(setup.srcDir + "/gui", setup.defines, setup.testDirs, in, ex);
createModuleList(setup.srcDir + "/audio", setup.defines, setup.testDirs, in, ex);
createModuleList(setup.srcDir + "/test", setup.defines, setup.testDirs, in, ex);
createProjectFile(setup.projectName, svmUUID, setup, setup.srcDir, in, ex);
} else if (!setup.devTools) {
// Last but not least create the main project file.
in.clear(); ex.clear();
// File list for the Project file
createModuleList(setup.srcDir + "/backends", setup.defines, in, ex);
createModuleList(setup.srcDir + "/backends/platform/sdl", setup.defines, in, ex);
createModuleList(setup.srcDir + "/base", setup.defines, in, ex);
createModuleList(setup.srcDir + "/common", setup.defines, in, ex);
createModuleList(setup.srcDir + "/engines", setup.defines, in, ex);
createModuleList(setup.srcDir + "/graphics", setup.defines, in, ex);
createModuleList(setup.srcDir + "/gui", setup.defines, in, ex);
createModuleList(setup.srcDir + "/audio", setup.defines, in, ex);
createModuleList(setup.srcDir + "/audio/softsynth/mt32", setup.defines, in, ex);
createModuleList(setup.srcDir + "/video", setup.defines, in, ex);
createModuleList(setup.srcDir + "/backends", setup.defines, setup.testDirs, in, ex);
createModuleList(setup.srcDir + "/backends/platform/sdl", setup.defines, setup.testDirs, in, ex);
createModuleList(setup.srcDir + "/base", setup.defines, setup.testDirs, in, ex);
createModuleList(setup.srcDir + "/common", setup.defines, setup.testDirs, in, ex);
createModuleList(setup.srcDir + "/engines", setup.defines, setup.testDirs, in, ex);
createModuleList(setup.srcDir + "/graphics", setup.defines, setup.testDirs, in, ex);
createModuleList(setup.srcDir + "/gui", setup.defines, setup.testDirs, in, ex);
createModuleList(setup.srcDir + "/audio", setup.defines, setup.testDirs, in, ex);
createModuleList(setup.srcDir + "/audio/softsynth/mt32", setup.defines, setup.testDirs, in, ex);
createModuleList(setup.srcDir + "/video", setup.defines, setup.testDirs, in, ex);
// Resource files
in.push_back(setup.srcDir + "/icons/" + setup.projectName + ".ico");
@ -1211,10 +1233,10 @@ void ProjectProvider::createProject(const BuildSetup &setup) {
// Create the main project file.
createProjectFile(setup.projectName, svmUUID, setup, setup.srcDir, in, ex);
// Create other misc. build files
createOtherBuildFiles(setup);
}
// Create other misc. build files
createOtherBuildFiles(setup);
}
ProjectProvider::UUIDMap ProjectProvider::createUUIDMap(const BuildSetup &setup) const {
@ -1322,7 +1344,7 @@ void ProjectProvider::addFilesToProject(const std::string &dir, std::ofstream &p
delete files;
}
void ProjectProvider::createModuleList(const std::string &moduleDir, const StringList &defines, StringList &includeList, StringList &excludeList) const {
void ProjectProvider::createModuleList(const std::string &moduleDir, const StringList &defines, StringList &testDirs, StringList &includeList, StringList &excludeList) const {
const std::string moduleMkFile = moduleDir + "/module.mk";
std::ifstream moduleMk(moduleMkFile.c_str());
if (!moduleMk)
@ -1453,6 +1475,59 @@ void ProjectProvider::createModuleList(const std::string &moduleDir, const Strin
++i;
}
}
} else if (*i == "TESTS") {
if (tokens.size() < 3)
error("Malformed TESTS definition in " + moduleMkFile);
++i;
if (*i != ":=" && *i != "+=" && *i != "=")
error("Malformed TESTS definition in " + moduleMkFile);
++i;
while (i != tokens.end()) {
// Read input
std::string folder = unifyPath(*i);
// Get include folder
const std::string source_dir = "$(srcdir)/";
const std::string selector = getLastPathComponent(folder);
const std::string module = getLastPathComponent(moduleDir);
folder.replace(folder.find(source_dir), source_dir.length(), "");
folder.replace(folder.find(selector), selector.length(), "");
folder.replace(folder.find(module), module.length(), moduleDir);
// Scan all files in the include folder
FileList files = listDirectory(folder);
if (files.empty())
continue;
// Add to list of test folders
testDirs.push_back(folder);
for (FileList::const_iterator f = files.begin(); f != files.end(); ++f) {
if (f->isDirectory)
continue;
std::string filename = folder + f->name;
if (shouldInclude.top()) {
// In case we should include a file, we need to make
// sure it is not in the exclude list already. If it
// is we just drop it from the exclude list.
excludeList.remove(filename);
includeList.push_back(filename);
} else if (std::find(includeList.begin(), includeList.end(), filename) == includeList.end()) {
// We only add the file to the exclude list in case it
// has not yet been added to the include list.
excludeList.push_back(filename);
}
}
++i;
}
} else if (*i == "ifdef") {
if (tokens.size() < 2)
error("Malformed ifdef in " + moduleMkFile);