Common::WriteStream *TestbedConfigManager::getConfigWriteStream() const { // Look for config file in game-path const Common::String &path = ConfMan.get("path"); Common::WriteStream *ws; Common::FSNode gameRoot(path); Common::FSNode config = gameRoot.getChild(_configFileName); ws = config.createWriteStream(); return ws; }
TestbedEngine::TestbedEngine(OSystem *syst) : Engine(syst) { // Put your engine in a sane state, but do nothing big yet; // in particular, do not load data from files; rather, if you // need to do such things, do them from init(). // Do not initialize graphics here // However this is the place to specify all default directories // Put game-data dir in search path Common::FSNode gameRoot(ConfMan.get("path")); if (gameRoot.exists()) { SearchMan.addDirectory(gameRoot.getDisplayName(), gameRoot); } DebugMan.addDebugChannel(kTestbedLogOutput, "LOG", "Log of test results generated by testbed"); DebugMan.addDebugChannel(kTestbedEngineDebug, "Debug", "Engine-specific debug statements"); DebugMan.enableDebugChannel("LOG"); // Initialize testsuites here // GFX Testsuite *ts = new GFXTestSuite(); _testsuiteList.push_back(ts); // FS ts = new FSTestSuite(); _testsuiteList.push_back(ts); // Savegames ts = new SaveGameTestSuite(); _testsuiteList.push_back(ts); // Misc. ts = new MiscTestSuite(); _testsuiteList.push_back(ts); // Events ts = new EventTestSuite(); _testsuiteList.push_back(ts); // Sound ts = new SoundSubsystemTestSuite(); _testsuiteList.push_back(ts); // Midi ts = new MidiTestSuite(); _testsuiteList.push_back(ts); #ifdef USE_LIBCURL // Cloud ts = new CloudTestSuite(); _testsuiteList.push_back(ts); #endif #ifdef USE_SDL_NET // Webserver ts = new WebserverTestSuite(); _testsuiteList.push_back(ts); #endif }
FSTestSuite::FSTestSuite() { // FS tests depend on Game Data files. // If those are not found. Disable this testsuite. const Common::String &path = ConfMan.get("path"); Common::FSNode gameRoot(path); Common::FSNode gameIdentificationFile = gameRoot.getChild("TESTBED"); if (!gameIdentificationFile.exists()) { logPrintf("WARNING! : Game Data not found. Skipping FS tests\n"); ConfParams.setGameDataFound(false); Testsuite::enable(false); } addTest("ReadingFile", &FStests::testReadFile, false); addTest("WritingFile", &FStests::testWriteFile, false); }
TestExitStatus CloudTests::testFolderDownloading() { ConfParams.setCloudTestCallbackCalled(false); ConfParams.setCloudTestErrorCallbackCalled(false); if (CloudMan.getCurrentStorage() == nullptr) { Testsuite::logPrintf("Couldn't find connected Storage\n"); return kTestFailed; } Common::String info = "Testing Cloud Storage API downloadFolder() method.\n" "In this test we'll try to download remote 'testbed/' directory."; if (Testsuite::handleInteractiveInput(info, "OK", "Skip", kOptionRight)) { Testsuite::logPrintf("Info! Skipping test : downloadFolder()\n"); return kTestSkipped; } const Common::String &path = ConfMan.get("path"); Common::FSDirectory gameRoot(path); Common::FSNode node = gameRoot.getFSNode().getChild("downloaded_directory"); Common::String filepath = node.getPath(); if (CloudMan.downloadFolder( getRemoteTestPath(), filepath.c_str(), new Common::GlobalFunctionCallback<Cloud::Storage::FileArrayResponse>(&directoryDownloadedCallback), new Common::GlobalFunctionCallback<Networking::ErrorResponse>(&errorCallback) ) == nullptr) { Testsuite::logPrintf("Warning! No Request is returned!\n"); } if (!waitForCallbackMore()) return kTestSkipped; Testsuite::clearScreen(); if (ConfParams.isCloudTestErrorCallbackCalled()) { Testsuite::logPrintf("Error callback was called\n"); return kTestFailed; } if (Testsuite::handleInteractiveInput("Was the CloudMan able to download into 'testbed/downloaded_directory'?", "Yes", "No", kOptionRight)) { Testsuite::logDetailedPrintf("Error! Directory was not downloaded!\n"); return kTestFailed; } Testsuite::logDetailedPrintf("Directory was downloaded\n"); return kTestPassed; }
TestExitStatus CloudTests::testSavesSync() { ConfParams.setCloudTestCallbackCalled(false); ConfParams.setCloudTestErrorCallbackCalled(false); if (CloudMan.getCurrentStorage() == nullptr) { Testsuite::logPrintf("Couldn't find connected Storage\n"); return kTestFailed; } Common::String info = "Testing Cloud Storage API syncSaves() method.\n" "In this test we'll try to sync your saves."; if (Testsuite::handleInteractiveInput(info, "OK", "Skip", kOptionRight)) { Testsuite::logPrintf("Info! Skipping test : syncSaves()\n"); return kTestSkipped; } const Common::String &path = ConfMan.get("path"); Common::FSDirectory gameRoot(path); Common::FSNode node = gameRoot.getFSNode().getChild("downloaded_directory"); Common::String filepath = node.getPath(); if (CloudMan.syncSaves( new Common::GlobalFunctionCallback<Cloud::Storage::BoolResponse>(&savesSyncedCallback), new Common::GlobalFunctionCallback<Networking::ErrorResponse>(&errorCallback) ) == nullptr) { Testsuite::logPrintf("Warning! No Request is returned!\n"); } if (!waitForCallbackMore()) return kTestSkipped; Testsuite::clearScreen(); if (ConfParams.isCloudTestErrorCallbackCalled()) { Testsuite::logPrintf("Error callback was called\n"); return kTestFailed; } if (Testsuite::handleInteractiveInput("Was the CloudMan able to sync saves?", "Yes", "No", kOptionRight)) { Testsuite::logDetailedPrintf("Error! Saves were not synced!\n"); return kTestFailed; } Testsuite::logDetailedPrintf("Saves were synced successfully\n"); return kTestPassed; }
/** * This test creates a file testbed.out, writes a sample data and confirms if * it is same by reading the file again. */ TestExitStatus FStests::testWriteFile() { const Common::String &path = ConfMan.get("path"); Common::FSNode gameRoot(path); if (!gameRoot.exists()) { Testsuite::logPrintf("Couldn't open the game data directory %s", path.c_str()); return kTestFailed; } Common::FSNode fileToWrite = gameRoot.getChild("testbed.out"); Common::WriteStream *ws = fileToWrite.createWriteStream(); if (!ws) { Testsuite::logDetailedPrintf("Can't open writable file in game data dir\n"); return kTestFailed; } ws->writeString("ScummVM Rocks!"); ws->flush(); delete ws; Common::SeekableReadStream *rs = fileToWrite.createReadStream(); if (!rs) { Testsuite::logDetailedPrintf("Can't open recently written file testbed.out in game data dir\n"); return kTestFailed; } Common::String readFromFile = rs->readLine(); delete rs; if (readFromFile.equals("ScummVM Rocks!")) { // All good Testsuite::logDetailedPrintf("Data written and read correctly\n"); return kTestPassed; } return kTestFailed; }
TestExitStatus FStests::testReadFile() { const Common::String &path = ConfMan.get("path"); Common::FSDirectory gameRoot(path); int numFailed = 0; if (!gameRoot.getFSNode().exists() || !gameRoot.getFSNode().isDirectory()) { Testsuite::logDetailedPrintf("game Path should be an existing directory"); return kTestFailed; } const char *dirList[] = {"test1" ,"Test2", "TEST3" , "tEST4", "test5"}; const char *file[] = {"file.txt", "File.txt", "FILE.txt", "fILe.txt", "file"}; for (unsigned int i = 0; i < ARRAYSIZE(dirList); i++) { Common::String dirName = dirList[i]; Common::String fileName = file[i]; Common::FSDirectory *directory = gameRoot.getSubDirectory(dirName); if (!directory) { Testsuite::logDetailedPrintf("Failed to open directory %s during FS tests\n", dirName.c_str()); return kTestFailed; } if (!readDataFromFile(directory, fileName.c_str())) { Testsuite::logDetailedPrintf("Reading from %s/%s failed\n", dirName.c_str(), fileName.c_str()); numFailed++; } dirName.toLowercase(); fileName.toLowercase(); delete directory; directory = gameRoot.getSubDirectory(dirName); if (!directory) { Testsuite::logDetailedPrintf("Failed to open directory %s during FS tests\n", dirName.c_str()); return kTestFailed; } if (!readDataFromFile(directory, fileName.c_str())) { Testsuite::logDetailedPrintf("Reading from %s/%s failed\n", dirName.c_str(), fileName.c_str()); numFailed++; } dirName.toUppercase(); fileName.toUppercase(); delete directory; directory = gameRoot.getSubDirectory(dirName); if (!directory) { Testsuite::logDetailedPrintf("Failed to open directory %s during FS tests\n", dirName.c_str()); return kTestFailed; } if (!readDataFromFile(directory, fileName.c_str())) { Testsuite::logDetailedPrintf("Reading from %s/%s failed\n", dirName.c_str(), fileName.c_str()); numFailed++; } delete directory; } Testsuite::logDetailedPrintf("Failed %d out of 15\n", numFailed); if (numFailed) { return kTestFailed; } else { return kTestPassed; } }
// ///////////////////////////////////////////////////////////////// // // ///////////////////////////////////////////////////////////////// bool LuaStateManager::Init(char const * const pInitFileName) { // Create our global actor table. // This table will hold context for all actors created in the game world. LuaPlus::LuaObject globals = m_GlobalState->GetGlobals(); LuaPlus::LuaObject actorTable = globals.CreateTable("ActorList"); // Execute the init file and setup some useful global variables for the lua scripts to know. if(DoFile(pInitFileName)) { std::string luaCommand; // The LUA command to execute. std::string currOpVal; // The current option value retrieved. boost::shared_ptr<GameOptions> opPtr = g_appPtr->GetGameOptions(); // Write out the location of the game root directory. boost::filesystem::path gameRoot(g_appPtr->GetGameRootDir()); //if(GameHalloran::RetrieveAndConvertOption<std::string>(opPtr, std::string("GameRoot"), GameHalloran::GameOptions::PROGRAMMER, currOpVal)) //{ luaCommand = std::string("INIT_GAME_ROOT_PATH = \"") + gameRoot.generic_string() + std::string("\";"); if(!ExecuteString(luaCommand.c_str())) { return (false); } currOpVal.clear(); luaCommand.clear(); //} // Write out what type of build is running. #ifdef DEBUG luaCommand = std::string("INIT_RUNNING_DEBUG_BUILD = true;"); #else luaCommand = std::string("INIT_RUNNING_DEBUG_BUILD = false;"); #endif if(!ExecuteString(luaCommand.c_str())) { return (false); } luaCommand.clear(); // Write out the various player options so they are available to the lua UI setup scripts. luaCommand = std::string("INIT_PLAYER_OPTIONS = {};"); if(!ExecuteString(luaCommand.c_str())) { return (false); } luaCommand.clear(); // Sound options. if(GameHalloran::RetrieveAndConvertOption<std::string>(opPtr, std::string("MasterVolume"), GameHalloran::GameOptions::PLAYER, currOpVal)) { luaCommand = std::string("INIT_PLAYER_OPTIONS.MasterVolume = ") + currOpVal + std::string(";"); if(!ExecuteString(luaCommand.c_str())) { return (false); } currOpVal.clear(); luaCommand.clear(); } bool flag; if(GameHalloran::RetrieveAndConvertOption<bool>(opPtr, std::string("Music"), GameHalloran::GameOptions::PLAYER, flag)) { luaCommand = std::string("INIT_PLAYER_OPTIONS.Music = ") + (flag ? std::string("true") : std::string("false")) + std::string(";"); if(!ExecuteString(luaCommand.c_str())) { return (false); } luaCommand.clear(); } if(GameHalloran::RetrieveAndConvertOption<bool>(opPtr, std::string("SoundFx"), GameHalloran::GameOptions::PLAYER, flag)) { luaCommand = std::string("INIT_PLAYER_OPTIONS.SoundFx = ") + (flag ? std::string("true") : std::string("false")) + std::string(";"); if(!ExecuteString(luaCommand.c_str())) { return (false); } luaCommand.clear(); } // Graphics options. if(GameHalloran::RetrieveAndConvertOption<bool>(opPtr, std::string("RenderShadows"), GameHalloran::GameOptions::PLAYER, flag)) { luaCommand = std::string("INIT_PLAYER_OPTIONS.RenderShadows = ") + (flag ? std::string("true") : std::string("false")) + std::string(";"); if(!ExecuteString(luaCommand.c_str())) { return (false); } luaCommand.clear(); } if(GameHalloran::RetrieveAndConvertOption<std::string>(opPtr, std::string("ScreenWidth"), GameHalloran::GameOptions::PLAYER, currOpVal)) { luaCommand = std::string("INIT_PLAYER_OPTIONS.ScreenResolution = \"") + currOpVal + std::string("*"); boost::shared_ptr<GameOptions> opPtr = g_appPtr->GetGameOptions(); if(GameHalloran::RetrieveAndConvertOption<std::string>(opPtr, std::string("ScreenHeight"), GameHalloran::GameOptions::PLAYER, currOpVal)) { luaCommand += currOpVal + std::string("\";"); if(!ExecuteString(luaCommand.c_str())) { return (false); } } currOpVal.clear(); luaCommand.clear(); } if(GameHalloran::RetrieveAndConvertOption<std::string>(opPtr, std::string("Multisampling"), GameHalloran::GameOptions::PLAYER, currOpVal)) { currOpVal = std::string("x") + currOpVal; luaCommand = std::string("INIT_PLAYER_OPTIONS.Multisampling = \"") + currOpVal + std::string("\";"); if(!ExecuteString(luaCommand.c_str())) { return (false); } currOpVal.clear(); luaCommand.clear(); } if(GameHalloran::RetrieveAndConvertOption<std::string>(opPtr, std::string("TextureFilteringType"), GameHalloran::GameOptions::PLAYER, currOpVal)) { luaCommand = std::string("INIT_PLAYER_OPTIONS.TextureFilteringType = \"") + currOpVal + std::string("\";"); if(!ExecuteString(luaCommand.c_str())) { return (false); } currOpVal.clear(); luaCommand.clear(); } return (true); } return (false); }
TestExitStatus CloudTests::testUploading() { ConfParams.setCloudTestCallbackCalled(false); ConfParams.setCloudTestErrorCallbackCalled(false); if (CloudMan.getCurrentStorage() == nullptr) { Testsuite::logPrintf("Couldn't find connected Storage\n"); return kTestFailed; } Common::String info = "Testing Cloud Storage API upload() method.\n" "In this test we'll try to upload a 'test1/file.txt' file."; if (Testsuite::handleInteractiveInput(info, "OK", "Skip", kOptionRight)) { Testsuite::logPrintf("Info! Skipping test : upload()\n"); return kTestSkipped; } if (!ConfParams.isGameDataFound()) { Testsuite::logPrintf("Info! Couldn't find the game data, so skipping test : upload()\n"); return kTestSkipped; } const Common::String &path = ConfMan.get("path"); Common::FSDirectory gameRoot(path); Common::FSDirectory *directory = gameRoot.getSubDirectory("test1"); Common::FSNode node = directory->getFSNode().getChild("file.txt"); delete directory; if (CloudMan.getCurrentStorage()->uploadStreamSupported()) { if (CloudMan.getCurrentStorage()->upload( Common::String(getRemoteTestPath()) + "/testfile.txt", node.createReadStream(), new Common::GlobalFunctionCallback<Cloud::Storage::UploadResponse>(&fileUploadedCallback), new Common::GlobalFunctionCallback<Networking::ErrorResponse>(&errorCallback) ) == nullptr) { Testsuite::logPrintf("Warning! No Request is returned!\n"); } } else { Common::String filepath = node.getPath(); if (CloudMan.getCurrentStorage()->upload( Common::String(getRemoteTestPath()) + "/testfile.txt", filepath.c_str(), new Common::GlobalFunctionCallback<Cloud::Storage::UploadResponse>(&fileUploadedCallback), new Common::GlobalFunctionCallback<Networking::ErrorResponse>(&errorCallback) ) == nullptr) { Testsuite::logPrintf("Warning! No Request is returned!\n"); } } if (!waitForCallbackMore()) return kTestSkipped; Testsuite::clearScreen(); if (ConfParams.isCloudTestErrorCallbackCalled()) { Testsuite::logPrintf("Error callback was called\n"); return kTestFailed; } Common::String info2 = "upload() is finished. Do you want to list '/testbed' directory?"; if (!Testsuite::handleInteractiveInput(info2, "Yes", "No", kOptionRight)) { ConfParams.setCloudTestCallbackCalled(false); if (CloudMan.listDirectory( getRemoteTestPath(), new Common::GlobalFunctionCallback<Cloud::Storage::FileArrayResponse>(&directoryListedCallback), new Common::GlobalFunctionCallback<Networking::ErrorResponse>(&errorCallback) ) == nullptr) { Testsuite::logPrintf("Warning! No Request is returned!\n"); } if (!waitForCallbackMore()) return kTestSkipped; Testsuite::clearScreen(); if (ConfParams.isCloudTestErrorCallbackCalled()) { Testsuite::logPrintf("Error callback was called\n"); return kTestFailed; } } if (Testsuite::handleInteractiveInput("Was the CloudMan able to upload into 'testbed/testfile.txt' file?", "Yes", "No", kOptionRight)) { Testsuite::logDetailedPrintf("Error! File was not uploaded!\n"); return kTestFailed; } Testsuite::logDetailedPrintf("File was uploaded\n"); return kTestPassed; }
void EnsureGamePath() { std::wstring fpath = MakeRelativeCitPath(L"CitizenFX.ini"); const wchar_t* pathKey = L"IVPath"; if (wcsstr(GetCommandLine(), L"cl2")) { pathKey = L"PathCL2"; } if (GetFileAttributes(fpath.c_str()) != INVALID_FILE_ATTRIBUTES) { wchar_t path[256]; GetPrivateProfileString(L"Game", pathKey, L"", path, _countof(path), fpath.c_str()); if (path[0] != L'\0') { return; } } ScopedCoInitialize coInit(COINIT_APARTMENTTHREADED); if (!coInit) { MessageBox(nullptr, va(L"CoInitializeEx failed. HRESULT = 0x%08x.", coInit.GetResult()), L"Error", MB_OK | MB_ICONERROR); ExitProcess(coInit.GetResult()); } WRL::ComPtr<IFileDialog> fileDialog; HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_IFileDialog, (void**)fileDialog.GetAddressOf()); if (FAILED(hr)) { MessageBox(nullptr, va(L"CoCreateInstance(IFileDialog) failed. HRESULT = 0x%08x.", hr), L"Error", MB_OK | MB_ICONERROR); ExitProcess(hr); } FILEOPENDIALOGOPTIONS opts; fileDialog->GetOptions(&opts); opts |= FOS_FORCEFILESYSTEM | FOS_PICKFOLDERS; fileDialog->SetOptions(opts); #ifndef GTA_FIVE fileDialog->SetTitle(L"Select the folder containing " GAME_EXECUTABLE); #else fileDialog->SetTitle(L"Select the folder containing Grand Theft Auto V"); // set the default folder, if we can find one { wchar_t gameRootBuf[1024]; DWORD gameRootLength = sizeof(gameRootBuf); // 5 is the amount of characters to strip off the end const std::tuple<std::wstring, std::wstring, int> folderAttempts[] = { { L"InstallFolderSteam", L"SOFTWARE\\WOW6432Node\\Rockstar Games\\GTAV", 5 }, { L"InstallFolder", L"SOFTWARE\\WOW6432Node\\Rockstar Games\\Grand Theft Auto V", 0 } }; for (const auto& folder : folderAttempts) { if (RegGetValue(HKEY_LOCAL_MACHINE, std::get<1>(folder).c_str(), std::get<0>(folder).c_str(), RRF_RT_REG_SZ, nullptr, gameRootBuf, &gameRootLength) == ERROR_SUCCESS) { WRL::ComPtr<IShellItem> item; std::wstring gameRoot(gameRootBuf); // strip \GTAV if needed gameRoot = gameRoot.substr(0, gameRoot.length() - std::get<int>(folder)); if (SUCCEEDED(SHCreateItemFromParsingName(gameRoot.c_str(), nullptr, IID_IShellItem, (void**)item.GetAddressOf()))) { auto checkFile = [&](const std::wstring& path) { return GetFileAttributesW((gameRoot + (L"\\" + path)).c_str()) != INVALID_FILE_ATTRIBUTES; }; fileDialog->SetFolder(item.Get()); if (checkFile(L"x64a.rpf") && checkFile(L"x64b.rpf") && checkFile(L"x64g.rpf") && checkFile(L"common.rpf") && checkFile(L"bink2w64.dll") && checkFile(L"x64\\audio\\audio_rel.rpf") && checkFile(L"GTA5.exe")) { WritePrivateProfileString(L"Game", pathKey, gameRoot.c_str(), fpath.c_str()); return; } } } } } #endif hr = fileDialog->Show(nullptr); if (FAILED(hr)) { if (hr != HRESULT_FROM_WIN32(ERROR_CANCELLED)) { MessageBox(nullptr, va(L"Could not show game folder selection window: IFileDialog::Show failed. HRESULT = 0x%08x.", hr), L"Error", MB_OK | MB_ICONERROR); } ExitProcess(0); } WRL::ComPtr<IShellItem> result; hr = fileDialog->GetResult(result.GetAddressOf()); if (!result) { MessageBox(nullptr, va(L"You did not select a game folder: IFileDialog::GetResult failed. HRESULT = 0x%08x.", hr), L"Error", MB_OK | MB_ICONERROR); ExitProcess(0); } PWSTR resultPath; if (FAILED(hr = result->GetDisplayName(SIGDN_FILESYSPATH, &resultPath))) { MessageBox(nullptr, va(L"Could not get game directory: IShellItem::GetDisplayName failed. HRESULT = 0x%08x.", hr), L"Error", MB_OK | MB_ICONERROR); ExitProcess(0); } // check if there's a game EXE in the path std::wstring gamePath = std::wstring(resultPath) + L"\\" GAME_EXECUTABLE; if (GetFileAttributes(gamePath.c_str()) == INVALID_FILE_ATTRIBUTES) { #if defined(GTA_NY) std::wstring eflcPath = std::wstring(resultPath) + L"\\EFLC.exe"; if (GetFileAttributes(eflcPath.c_str()) != INVALID_FILE_ATTRIBUTES) { MessageBox(nullptr, L"The selected path does not contain a GTAIV.exe file. As this is an EFLC installation, placing a GTAIV.exe (version 1.0.7.0) from any source will work as well.", PRODUCT_NAME, MB_OK | MB_ICONWARNING); } else #endif { MessageBox(nullptr, L"The selected path does not contain a " GAME_EXECUTABLE L" file.", PRODUCT_NAME, MB_OK | MB_ICONWARNING); } ExitProcess(0); } WritePrivateProfileString(L"Game", pathKey, resultPath, fpath.c_str()); CoTaskMemFree(resultPath); }