Ticket #1396: track1396.patch
File track1396.patch, 50.1 KB (added by , 10 years ago) |
---|
-
binaries/data/mods/_test.sim/simulation/components/test-bom-none.js
1 /* A simple JavaScript file in UTF-8 without byte order mark 2 at the start of the file, to ensure such scripts are handled 3 properly. */ 4 Engine.Note = "Script without BOM was accepted"; -
binaries/data/mods/_test.sim/simulation/components/test-bom-utf8.js
1 /* A simple JavaScript file in UTF-8 with byte order mark/ at the start 2 of the file (probably not visible in a regular editor), to ensure such 3 scripts are handled properly.*/ 4 5 Engine.Note = "UTF8-BOM was accepted"; /* ID to ensure 6 the function was really evaluated ☺ */ -
source/gui/CGUI.h
421 421 void Xeromyces_ReadRootSetup(XMBElement Element, CXeromyces* pFile); 422 422 423 423 // Read Subs 424 424 protected: // Members protected so unit tests can access them via inheritance 425 425 426 /** 426 427 * Notice! Recursive function! 427 428 * -
source/gui/tests/test_CGUI.h
1 /* Copyright (C) 2014 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "gui/CGUI.h" 19 #include "gui/IGUIObject.h" 20 #include "lib/utf8.h" 21 #include "lib/file/file.h" 22 #include "lib/file/vfs/vfs.h" 23 #include "scriptinterface/ScriptInterface.h" 24 #include "ps/CLogger.h" 25 #include "ps/Filesystem.h" 26 27 /** 28 * Helper namespace to keep utility classes for testing of CGUI, namely 29 * the VFS fakes (prevent collision with other tests) 30 */ 31 namespace test_CGUI 32 { 33 /** 34 * Lightweight testing implementation of a virtual file system. 35 * 36 * While the TestSimulation2 class already has an associated mod (_test.sim), 37 * testing of the file loader routines via a stub has several advantages: 38 * 1. Some routines, such as GetRMSData(), scan a whole directory whose path is 39 * hard-coded in the testee. Using a real VFS might cause undesired interferences 40 * as more tests are added for a single routine. 41 * 2. A pure in-memory VFS is much faster. 42 * 3. For UTF-8 tests, control characters (such as a leading BOM) may be expressed 43 * directly in the C code, while they might be invisible in some editors when 44 * put in real files. 45 */ 46 struct StubVFS : public IVFS { 47 48 /** 49 * Simulates a file. 50 */ 51 class StubFile 52 { 53 public: 54 55 /** 56 * Initializes a new stub file with fixed content. 57 * @param filename Name of the file. 58 * @param dataLength Size of the data held by the fake file. 59 * @param data Data found in the associated file. 60 */ 61 StubFile(const char filename[], size_t dataLength, const u8 data[]) : 62 m_FileName(filename), 63 m_FileSize(dataLength) 64 { 65 u8 *dataCopy = new u8[dataLength]; 66 memcpy(dataCopy, data, dataLength); 67 this->m_FileContent = shared_ptr<u8>(dataCopy); 68 } 69 70 /** 71 * Provides the data size of the file. 72 * @return An info record with file size and a fake date. 73 */ 74 CFileInfo getInfo() const 75 { 76 return CFileInfo(this->getName(), this->m_FileSize, 0); 77 } 78 79 /** 80 * Retrieves the name of the file. 81 * @return The filename passed into the constructor. 82 */ 83 OsPath getName() const 84 { 85 return OsPath(this->m_FileName); 86 } 87 88 /** 89 * Retrieves the data of this file. 90 * @return A copy of the data passed to the constructor. 91 */ 92 shared_ptr<u8> getContent() const 93 { 94 return this->m_FileContent; 95 } 96 97 private: 98 99 /** 100 * Name of this file. 101 */ 102 const char *m_FileName; 103 104 /** 105 * Data found in the file represented by this object 106 */ 107 shared_ptr<u8> m_FileContent; 108 109 /** 110 * Data size of 'm_FileContent' 111 */ 112 const size_t m_FileSize; 113 }; 114 115 /** 116 * Creates a stub file system which simulates a fixed set of files. 117 * @param numberOfFiles Number of valid entries in 'files'. 118 * @param files The files which are provided (no real support for 119 * directories, all files are returned on each call to 120 * 'GetDirectoryEntries'). 121 */ 122 StubVFS(size_t numberOfFiles, const StubFile files[]) : 123 m_NumberOfFiles(numberOfFiles) 124 { 125 this->m_Files = files; 126 } 127 128 virtual Status Mount(const VfsPath&, const OsPath&, size_t, size_t) 129 { 130 throw "Not yet implemented"; 131 } 132 133 virtual Status GetFileInfo(const VfsPath &path, CFileInfo *pInfo) const 134 { 135 for (size_t i = 0; i < this->m_NumberOfFiles; i++) 136 { 137 if (this->m_Files[i].getName() == path.Filename()) 138 { 139 if (pInfo) 140 { 141 *pInfo = this->m_Files[i].getInfo(); 142 } 143 return INFO::OK; 144 } 145 } 146 return ERR::FILE_NOT_FOUND; 147 } 148 149 virtual Status GetFilePriority(const VfsPath &path, size_t *ppriority) const 150 { 151 for (size_t i = 0; i < this->m_NumberOfFiles; i++) 152 { 153 if (this->m_Files[i].getName() == path.Filename()) 154 { 155 *ppriority = 1; 156 return INFO::OK; 157 } 158 } 159 return ERR::FILE_NOT_FOUND; 160 } 161 162 /** 163 * Retrieves a listing of all files held by this file system. 164 * @param infos Receives additional information about a file. 165 * @param names Receives the names of all files in the file system. 166 * @return OK. 167 */ 168 virtual Status GetDirectoryEntries(const VfsPath&, CFileInfos* infos, DirectoryNames* names) const 169 { 170 for (size_t i = 0; i < this->m_NumberOfFiles; i++) 171 { 172 if (infos) 173 { 174 infos->push_back(this->m_Files[i].getInfo()); 175 } 176 if (names) 177 { 178 names->push_back(this->m_Files[i].getName()); 179 } 180 } 181 return INFO::OK; 182 } 183 184 virtual Status CreateFile(const VfsPath &, const shared_ptr<u8>&, size_t) 185 { 186 // Currently, test cases do not involve writing files back to disk; 187 // this function is called by Xeromyces in an attempt to cache an XML 188 // document in binary mode 189 return INFO::OK; 190 } 191 192 virtual Status ReplaceFile(const VfsPath&, const shared_ptr<u8>&, size_t) 193 { 194 throw "Not yet implemented"; 195 } 196 197 /** 198 * Read an entire file into memory. 199 * 200 * @param path Selects the fake file whose content is requested. 201 * @param fileContents receives a smart pointer to the contents. 202 * CAVEAT: this will be taken from the file cache if the VFS was 203 * created with cacheSize != 0 and size < cacheSize. There is no 204 * provision for Copy-on-Write, which means that such buffers 205 * must not be modified (this is enforced via mprotect). 206 * @param size receives the size [bytes] of the file contents. 207 * @return OK, if a fake file with given path was selected, or 208 * OpenFailed in case the file does not exist. 209 **/ 210 virtual Status LoadFile(const VfsPath& path, shared_ptr<u8>& fileContents, size_t& size) 211 { 212 for (size_t i = 0; i < this->m_NumberOfFiles; i++) 213 { 214 if (this->m_Files[i].getName() == path.Filename()) 215 { 216 fileContents = this->m_Files[i].getContent(); 217 size = this->m_Files[i].getInfo().Size(); 218 return INFO::OK; 219 } 220 } 221 return CODE__PSRETURN_Scripting_LoadFile_OpenFailed; 222 } 223 224 virtual std::wstring TextRepresentation() const 225 { 226 throw "Not yet implemented"; 227 } 228 229 virtual Status GetRealPath(const VfsPath &virtualPath, OsPath &realPath) 230 { 231 realPath = virtualPath; 232 return INFO::OK; 233 } 234 235 virtual Status GetDirectoryRealPath(const VfsPath&, OsPath&) 236 { 237 throw "Not yet implemented"; 238 } 239 240 virtual Status GetVirtualPath(const OsPath&, VfsPath&) 241 { 242 throw "Not yet implemented"; 243 } 244 245 /** 246 * remove file from the virtual directory listing and evict its 247 * data from the cache. 248 **/ 249 virtual Status RemoveFile(const VfsPath&) 250 { 251 throw "Not yet implemented"; 252 } 253 254 virtual Status RepopulateDirectory(const VfsPath&) 255 { 256 throw "Not yet implemented"; 257 } 258 259 virtual void Clear() 260 { 261 throw "Not yet implemented"; 262 } 263 264 private: 265 266 /** 267 * Number of valid elements in 'm_Files'. 268 */ 269 const size_t m_NumberOfFiles; 270 271 /** 272 * The files found in this file system. 273 */ 274 const StubFile *m_Files; 275 }; 276 277 /** 278 * Helper to collect the actual elements loaded from Xeromyces 279 */ 280 class MockGUIObject : public IGUIObject 281 { 282 public: 283 284 virtual void Draw(void) 285 { 286 // No need to draw anything, used only for testing 287 } 288 289 /** 290 * Retrieves the first child from the internal list of children. 291 * @return A reference to the first child, NULL if there are no children. 292 */ 293 IGUIObject *GetFirstChild() 294 { 295 return this->m_Children.size() > 0 ? this->m_Children[0] : NULL; 296 } 297 298 /** 299 * Helper member for the BOM tests to run the JavaScript handlers registered 300 * by the Xeromyces loader 301 */ 302 virtual void HandleMessage(SGUIMessage& UNUSED(Message)) 303 { 304 this->ScriptEvent("validatetest"); 305 } 306 307 }; 308 } 309 310 class TestCGUI : public CxxTest::TestSuite 311 { 312 public: 313 314 class CGUI_TestHook : public CGUI 315 { 316 public: 317 CGUI_TestHook(const shared_ptr<ScriptRuntime>& runtime) : CGUI(runtime) 318 { 319 } 320 321 void Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObject *pParent, const std::vector<std::pair<CStr, CStr> >& NameSubst, boost::unordered_set<VfsPath>& Paths) 322 { 323 CGUI::Xeromyces_ReadObject(Element, pFile, pParent, NameSubst, Paths); 324 } 325 326 }; 327 328 329 void setUp() 330 { 331 CXeromyces::Startup(); 332 } 333 334 void tearDown() 335 { 336 CXeromyces::Terminate(); 337 } 338 339 static IGUIObject *CreateMockObject() 340 { 341 return new test_CGUI::MockGUIObject(); 342 } 343 344 /** 345 * An action handler (external JavaScript file) is loaded when stored as a 346 * raw ASCII file. 347 */ 348 void test_Xeromyces_ReadObject_RawASCIISupportedAsActionScript() 349 { 350 const u8 xmlData[] = "\ 351 <object type=\"testobj\">\ 352 <action file=\"test.js\" on=\"validatetest\"/>\ 353 </object>"; 354 const u8 jsData[] = "warn(\"Raw ASCII accepted!\");"; 355 356 test_CGUI::StubVFS::StubFile testFiles[] = 357 { 358 test_CGUI::StubVFS::StubFile("test.xml", sizeof(xmlData)/sizeof(xmlData[0]) - 1, xmlData), 359 test_CGUI::StubVFS::StubFile("test.js", sizeof(jsData)/sizeof(jsData[0]) - 1, jsData) 360 }; 361 PIVFS originalVFS(g_VFS); 362 g_VFS = PIVFS(new test_CGUI::StubVFS(2, testFiles)); 363 364 CXeromyces testObjDescription; 365 PSRETURN loadingResult = testObjDescription.Load(g_VFS, "test.xml"); 366 367 TS_ASSERT_EQUALS(loadingResult, INFO::OK); 368 369 XMBElement rootNode = testObjDescription.GetRoot(); 370 371 CGUI_TestHook testee(ScriptInterface::CreateRuntime()); 372 std::vector<std::pair<CStr8, CStr8> > nameSubst; 373 boost::unordered_set<VfsPath> vfsPaths; 374 test_CGUI::MockGUIObject mockParent; 375 376 testee.AddObjectType("testobj", &CreateMockObject); 377 378 testee.Xeromyces_ReadObject( 379 rootNode, 380 &testObjDescription, 381 &mockParent, 382 nameSubst, 383 vfsPaths); 384 385 IGUIObject *pGeneratedChild = mockParent.GetFirstChild(); 386 387 // If the test setup above is successfull, pGeneratedChild 388 // is actually a MockGUIObject and its HandleMessage implementation 389 // will run the JavaScript code. 390 TS_ASSERT(NULL != pGeneratedChild); 391 392 TestLogger log; 393 394 SGUIMessage message(GUIM_MOUSE_OVER); 395 pGeneratedChild->HandleMessage(message); 396 397 TS_ASSERT_WSTR_CONTAINS(log.GetOutput(), L"Raw ASCII accepted!"); 398 399 g_VFS = originalVFS; 400 } 401 402 /** 403 * An action handler (external JavaScript file) is loaded when stored with 404 * an UTF-8 byte-order-mark at the start of the script code, leaving valid 405 * JavaScript. 406 */ 407 void test_Xeromyces_ReadObject_UTF8SupportedAsActionScript() 408 { 409 const u8 xmlData[] = "\ 410 <object type=\"testobj\">\ 411 <action file=\"test.js\" on=\"validatetest\"/>\ 412 </object>"; 413 const u8 jsData[] = "\xEF\xBB\xBFwarn(\"UTF8-BOM accepted!\");"; 414 415 test_CGUI::StubVFS::StubFile testFiles[] = 416 { 417 test_CGUI::StubVFS::StubFile("test.xml", sizeof(xmlData)/sizeof(xmlData[0]) - 1, xmlData), 418 test_CGUI::StubVFS::StubFile("test.js", sizeof(jsData)/sizeof(jsData[0]) - 1, jsData) 419 }; 420 PIVFS originalVFS(g_VFS); 421 g_VFS = PIVFS(new test_CGUI::StubVFS(2, testFiles)); 422 423 CXeromyces testObjDescription; 424 PSRETURN loadingResult = testObjDescription.Load(g_VFS, "test.xml"); 425 426 TS_ASSERT_EQUALS(loadingResult, INFO::OK); 427 428 XMBElement rootNode = testObjDescription.GetRoot(); 429 430 CGUI_TestHook testee(ScriptInterface::CreateRuntime()); 431 std::vector<std::pair<CStr8, CStr8> > nameSubst; 432 boost::unordered_set<VfsPath> vfsPaths; 433 test_CGUI::MockGUIObject mockParent; 434 435 testee.AddObjectType("testobj", &CreateMockObject); 436 437 testee.Xeromyces_ReadObject( 438 rootNode, 439 &testObjDescription, 440 &mockParent, 441 nameSubst, 442 vfsPaths); 443 444 IGUIObject *pGeneratedChild = mockParent.GetFirstChild(); 445 446 // If the test setup above is successfull, pGeneratedChild 447 // is actually a MockGUIObject and its HandleMessage implementation 448 // will run the JavaScript code 449 TS_ASSERT(NULL != pGeneratedChild); 450 451 TestLogger log; 452 453 SGUIMessage message(GUIM_MOUSE_OVER); 454 pGeneratedChild->HandleMessage(message); 455 456 TS_ASSERT_WSTR_CONTAINS(log.GetOutput(), L"UTF8-BOM accepted!"); 457 458 g_VFS = originalVFS; 459 } 460 461 }; -
source/ps/GameSetup/HWDetect.cpp
186 186 g_RenderPath = renderpath; 187 187 } 188 188 189 void RunHardwareDetection() 189 /** 190 * Loads and initializes the JavaScript library used for hardware 191 * detection. 192 * @param scriptInterface The runtime used for the JS part of the HW detection. 193 * @return true if and only if the script was loaded successfully. 194 */ 195 bool LoadHardwareDetectionLibrary(ScriptInterface &scriptInterface) 190 196 { 191 TIMER(L"RunHardwareDetection");192 193 ScriptInterface scriptInterface("Engine", "HWDetect", g_ScriptRuntime);194 195 197 scriptInterface.RegisterFunction<void, bool, &SetDisableAudio>("SetDisableAudio"); 196 198 scriptInterface.RegisterFunction<void, bool, &SetDisableS3TC>("SetDisableS3TC"); 197 199 scriptInterface.RegisterFunction<void, bool, &SetDisableShadows>("SetDisableShadows"); … … 208 210 if (file.Load(g_VFS, scriptName) != PSRETURN_OK) 209 211 { 210 212 LOGERROR(L"Failed to load hardware detection script"); 211 return ;213 return false; 212 214 } 213 215 214 216 std::string code = file.DecodeUTF8(); // assume it's UTF-8 215 scriptInterface.LoadScript(scriptName, code); 217 return scriptInterface.LoadScript(scriptName, code); 218 } 216 219 220 void RunHardwareDetection() 221 { 222 TIMER(L"RunHardwareDetection"); 223 224 ScriptInterface scriptInterface("Engine", "HWDetect", g_ScriptRuntime); 225 226 if (LoadHardwareDetectionLibrary(scriptInterface)) 227 { 228 return; 229 } 230 217 231 // Collect all the settings we'll pass to the script: 218 232 // (We'll use this same data for the opt-in online reporting system, so it 219 233 // includes some fields that aren't directly useful for the hwdetect script) -
source/ps/GameSetup/tests/test_HWDetect.h
1 /* Copyright (C) 2010 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "lib/file/vfs/vfs.h" 19 #include "scriptinterface/ScriptInterface.h" 20 #include "ps/Filesystem.h" 21 #include "ps/GameSetup/Config.h" 22 #include "ps/GameSetup/HWDetect.h" 23 24 /** 25 * Holds utility classes for testing of the HWDetection routines 26 * 27 * Multiple classes use stub implementation of the IVFS 28 * interface; to prevent name collisions among them, the stub is 29 * encapsulated in its own namespace. 30 */ 31 namespace test_HWDetect 32 { 33 34 /** 35 * Lightweight testing implementation of a virtual file system. 36 */ 37 struct StubVFS : public IVFS { 38 39 /** 40 * Creates a stub file system which returns a fixed file content for any file. 41 * @param dataLength Number of valid consecutive data bytes in 'fileContent'. 42 * @param fileContent "Data" of all files in the stub file system. 43 */ 44 StubVFS(size_t dataLength, const u8 fileContent[]) : m_FileSize(dataLength) 45 { 46 // As the IVFS is defined to return a smart pointer to the data - 47 // see LoadFile() - we have to create a copy of the supplied primitive 48 // memory block, getting rid of the const at the same time. 49 50 u8 *dataCopy = new u8[dataLength]; 51 memcpy(dataCopy, fileContent, dataLength); 52 this->m_FileContent = shared_ptr<u8>(dataCopy); 53 } 54 55 virtual Status Mount(const VfsPath&, const OsPath&, size_t, size_t) 56 { 57 throw "Not yet implemented"; 58 } 59 60 virtual Status GetFileInfo(const VfsPath&, CFileInfo*) const 61 { 62 throw "Not yet implemented"; 63 } 64 65 virtual Status GetFilePriority(const VfsPath&, size_t*) const 66 { 67 throw "Not yet implemented"; 68 } 69 70 virtual Status GetDirectoryEntries(const VfsPath&, CFileInfos*, DirectoryNames*) const 71 { 72 throw "Not yet implemented"; 73 } 74 75 virtual Status CreateFile(const VfsPath&, const shared_ptr<u8>&, size_t) 76 { 77 throw "Not yet implemented"; 78 } 79 80 virtual Status ReplaceFile(const VfsPath&, const shared_ptr<u8>&, size_t) 81 { 82 throw "Not yet implemented"; 83 } 84 85 /** 86 * Read an entire file into memory. 87 * 88 * @param fileContents receives a smart pointer to the contents. 89 * CAVEAT: this will be taken from the file cache if the VFS was 90 * created with cacheSize != 0 and size < cacheSize. There is no 91 * provision for Copy-on-Write, which means that such buffers 92 * must not be modified (this is enforced via mprotect). 93 * @param size receives the size [bytes] of the file contents. 94 * @return Status. 95 **/ 96 virtual Status LoadFile(const VfsPath&, shared_ptr<u8>& fileContents, size_t& size) 97 { 98 fileContents = this->m_FileContent; 99 size = this->m_FileSize; 100 return INFO::OK; 101 } 102 103 virtual std::wstring TextRepresentation() const 104 { 105 throw "Not yet implemented"; 106 } 107 108 virtual Status GetRealPath(const VfsPath&, OsPath&) 109 { 110 throw "Not yet implemented"; 111 } 112 113 virtual Status GetDirectoryRealPath(const VfsPath&, OsPath&) 114 { 115 throw "Not yet implemented"; 116 } 117 118 virtual Status GetVirtualPath(const OsPath&, VfsPath&) 119 { 120 throw "Not yet implemented"; 121 } 122 123 virtual Status RemoveFile(const VfsPath&) 124 { 125 throw "Not yet implemented"; 126 } 127 128 virtual Status RepopulateDirectory(const VfsPath&) 129 { 130 throw "Not yet implemented"; 131 } 132 133 virtual void Clear() 134 { 135 throw "Not yet implemented"; 136 } 137 138 private: 139 140 /** 141 * Data found in all "files" of this file system. 142 */ 143 shared_ptr<u8> m_FileContent; 144 145 /** 146 * Number of valid elements in 'm_FileContent' 147 */ 148 const size_t m_FileSize; 149 }; 150 151 } 152 153 // In theory, the loader function should not be visible outside HWDetect.cpp, 154 // but since that file is procedural, the usual trick of declaring friend with 155 // the testee cannot be used to gain access to the function tested. As a 156 // compromise, the prototype is declared in the test only. 157 extern bool LoadHardwareDetectionLibrary(ScriptInterface &scriptInterface); 158 159 class TestHWDetect : public CxxTest::TestSuite 160 { 161 public: 162 163 /** 164 * The hardware detection JavaScript used by the HWDetect sub-module is accepted 165 * when it contains a lead-in byte order mark. 166 */ 167 void test_LoadHWDetection_accepts_BOM() 168 { 169 static const u8 detectionScript[] = "\xEF\xBB\xBF Engine.SetRenderPath(\"BOM accepted\");"; 170 PIVFS originalVFS(g_VFS); 171 CStr originalRenderPath(g_RenderPath); 172 173 g_VFS = 174 PIVFS(new test_HWDetect::StubVFS( 175 sizeof(detectionScript)/sizeof(detectionScript[0]) - 1, // -1 as JS does not accept \0 176 detectionScript)); 177 178 shared_ptr<ScriptRuntime> runtime = ScriptInterface::CreateRuntime(); 179 ScriptInterface scriptInterface("Engine", "HWDetect", runtime); 180 181 LoadHardwareDetectionLibrary(scriptInterface); 182 183 TS_ASSERT_EQUALS(g_RenderPath, "BOM accepted"); 184 185 g_VFS = originalVFS; 186 g_RenderPath = originalRenderPath; 187 } 188 189 /** 190 * The hardware detection JavaScript used by the HWDetect.cpp sub-module is accepted 191 * when it does not start with a byte-order-mark (e.g. a plain ASCII file) 192 */ 193 void test_LoadHWDetection_accepts_without_BOM() 194 { 195 static const u8 detectionScript[] = "Engine.SetRenderPath(\"ASCII accepted\");"; 196 PIVFS originalVFS(g_VFS); 197 CStr originalRenderPath(g_RenderPath); 198 199 g_VFS = 200 PIVFS(new test_HWDetect::StubVFS( 201 sizeof(detectionScript)/sizeof(detectionScript[0]) - 1, // -1 as JS does not accept \0 202 detectionScript)); 203 204 shared_ptr<ScriptRuntime> runtime = ScriptInterface::CreateRuntime(); 205 ScriptInterface scriptInterface("Engine", "HWDetect", runtime); 206 207 LoadHardwareDetectionLibrary(scriptInterface); 208 209 TS_ASSERT_EQUALS(g_RenderPath, "ASCII accepted"); 210 211 g_VFS = originalVFS; 212 g_RenderPath = originalRenderPath; 213 } 214 215 }; -
source/ps/tests/test_CVFSFile.h
1 /* Copyright (C) 2012 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "precompiled.h" 19 #include "ps/Filesystem.h" 20 21 /** 22 * Holds utility classes for testing of the CVFSFile class. 23 * 24 * The unit-tests of the CVFSFile use a stub implementation of the IVFS 25 * interface; to prevent name collisions with other tests, the stub is 26 * encapsulated in its own namespace. 27 */ 28 namespace test_CVFSFile 29 { 30 31 /** 32 * Lightweight testing implementation of a virtual file system. 33 */ 34 struct StubVFS : public IVFS { 35 36 /** 37 * Creates a stub file system which returns a fixed file content for any file. 38 * @param dataLength Number of valid consecutive data bytes in 'fileContent'. 39 * @param fileContent "Data" of all files in the stub file system. 40 */ 41 StubVFS(size_t dataLength, const u8 fileContent[]) : m_FileSize(dataLength) 42 { 43 // As the IVFS is defined to return a smart pointer to the data - 44 // see LoadFile() - we have to create a copy of the supplied primitive 45 // memory block, getting rid of the const at the same time. 46 47 u8 *dataCopy = new u8[dataLength]; 48 memcpy(dataCopy, fileContent, dataLength); 49 this->m_FileContent = shared_ptr<u8>(dataCopy); 50 } 51 52 virtual Status Mount(const VfsPath&, const OsPath&, size_t, size_t) 53 { 54 throw "Not yet implemented"; 55 } 56 57 virtual Status GetFileInfo(const VfsPath&, CFileInfo*) const 58 { 59 throw "Not yet implemented"; 60 } 61 62 virtual Status GetFilePriority(const VfsPath&, size_t*) const 63 { 64 throw "Not yet implemented"; 65 } 66 67 virtual Status GetDirectoryEntries(const VfsPath&, CFileInfos*, DirectoryNames*) const 68 { 69 throw "Not yet implemented"; 70 } 71 72 virtual Status CreateFile(const VfsPath&, const shared_ptr<u8>&, size_t) 73 { 74 75 throw "Not yet implemented"; 76 } 77 78 virtual Status ReplaceFile(const VfsPath&, const shared_ptr<u8>&, size_t) 79 { 80 throw "Not yet implemented"; 81 } 82 83 /** 84 * Read an entire file into memory. 85 * 86 * @param fileContents receives a smart pointer to the contents. 87 * CAVEAT: this will be taken from the file cache if the VFS was 88 * created with cacheSize != 0 and size < cacheSize. There is no 89 * provision for Copy-on-Write, which means that such buffers 90 * must not be modified (this is enforced via mprotect). 91 * @param size receives the size [bytes] of the file contents. 92 * @return Status. 93 **/ 94 virtual Status LoadFile(const VfsPath&, shared_ptr<u8>& fileContents, size_t& size) 95 { 96 fileContents = this->m_FileContent; 97 size = this->m_FileSize; 98 return INFO::OK; 99 } 100 101 virtual std::wstring TextRepresentation() const 102 { 103 throw "Not yet implemented"; 104 } 105 106 virtual Status GetRealPath(const VfsPath&, OsPath&) 107 { 108 throw "Not yet implemented"; 109 } 110 111 virtual Status GetDirectoryRealPath(const VfsPath&, OsPath&) 112 { 113 throw "Not yet implemented"; 114 } 115 116 virtual Status GetVirtualPath(const OsPath&, VfsPath&) 117 { 118 throw "Not yet implemented"; 119 } 120 121 /** 122 * remove file from the virtual directory listing and evict its 123 * data from the cache. 124 **/ 125 virtual Status RemoveFile(const VfsPath&) 126 { 127 throw "Not yet implemented"; 128 } 129 130 virtual Status RepopulateDirectory(const VfsPath&) 131 { 132 throw "Not yet implemented"; 133 } 134 135 virtual void Clear() 136 { 137 throw "Not yet implemented"; 138 } 139 140 private: 141 142 /** 143 * Data found in all "files" of this file system. 144 */ 145 shared_ptr<u8> m_FileContent; 146 147 /** 148 * Number of valid elements in 'm_FileContent' 149 */ 150 const size_t m_FileSize; 151 }; 152 153 } 154 155 class TestCVSFFile : public CxxTest::TestSuite 156 { 157 public: 158 159 /** 160 * A file without an UTF8 byte order mark at the start (e.g. a normal 161 * ASCII file) is loaded properly. 162 */ 163 void test_decodeutf8_works_without_bom() 164 { 165 static const unsigned char testContent[] = 166 { 167 'S', 'm', 'i', 'l', 'e', 'y', ' ', 168 ':', '-', ')' 169 }; 170 171 PIVFS pvfs = 172 PIVFS(new test_CVFSFile::StubVFS( 173 sizeof(testContent)/sizeof(testContent[0]), 174 testContent)); 175 176 CVFSFile testObj; 177 178 PSRETURN state = testObj.Load(pvfs, "Testfile.txt"); 179 180 TS_ASSERT_EQUALS(state, PSRETURN_OK); 181 182 CStr decodedStr = testObj.DecodeUTF8(); 183 184 TS_ASSERT_EQUALS(decodedStr[0], 'S'); 185 TS_ASSERT_EQUALS(decodedStr[2], 'i'); 186 TS_ASSERT_EQUALS(decodedStr.size(), 187 sizeof(testContent) / sizeof(testContent[0])); 188 } 189 190 /** 191 * A file with an UTF8 byte order mark at the start is loaded correctly, 192 * and the byte order mark suppressed on decoding. 193 */ 194 void test_decodeutf8_accepts_bom() 195 { 196 const size_t BOM_LENGTH = 3; 197 static const unsigned char testContent[] = 198 { 199 0xEF, 0xBB, 0xBF, // Byte order mark sequence 200 'S', 'm', 'i', 'l', 'e', 'y', ' ', // regular text 201 0xE2, 0x98, 0xBA // smiley (263Ah) 202 }; 203 204 PIVFS pvfs = 205 PIVFS(new test_CVFSFile::StubVFS( 206 sizeof(testContent)/sizeof(testContent[0]), 207 testContent)); 208 209 CVFSFile testObj; 210 211 PSRETURN state = testObj.Load(pvfs, "Testfile.txt"); 212 213 TS_ASSERT_EQUALS(state, PSRETURN_OK); 214 215 CStr decodedStr = testObj.DecodeUTF8(); 216 217 TS_ASSERT_EQUALS(decodedStr[0], 'S'); 218 TS_ASSERT_EQUALS(decodedStr[2], 'i'); 219 TS_ASSERT_EQUALS(decodedStr.size(), 220 sizeof(testContent) / sizeof(testContent[0]) - BOM_LENGTH); 221 } 222 223 }; -
source/scriptinterface/tests/test_ScriptInterface.h
15 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 16 */ 17 17 18 #include "lib/file/vfs/vfs.h" 18 19 #include "lib/self_test.h" 19 20 20 21 #include "scriptinterface/ScriptInterface.h" 21 22 22 23 #include "ps/CLogger.h" 24 #include "ps/Filesystem.h" 23 25 24 26 #include <boost/random/linear_congruential.hpp> 25 27 28 /** 29 * Helper namespace to keep utility classes for ScriptInterface unit tests. 30 */ 31 namespace test_ScriptInterface 32 { 33 34 /** 35 * Lightweight testing implementation of a virtual file system. Intended for unit 36 * tests only (escape the need to provide actual files on the disk, and reading 37 * them each time a new test class is launched) 38 */ 39 struct StubVFS : public IVFS { 40 41 /** 42 * Creates a stub file system which returns a fixed file content for any file. 43 * @param dataLength Number of valid consecutive data bytes in 'fileContent'. 44 * @param fileContent "Data" of all files in the stub file system. 45 */ 46 StubVFS(size_t dataLength, const u8 fileContent[]) : m_FileSize(dataLength) 47 { 48 // As the IVFS is defined to return a smart pointer to the data - 49 // see LoadFile() - we have to create a copy of the supplied primitive 50 // memory block, getting rid of the const at the same time. 51 52 u8 *dataCopy = new u8[dataLength]; 53 memcpy(dataCopy, fileContent, dataLength); 54 this->m_FileContent = shared_ptr<u8>(dataCopy); 55 } 56 57 virtual Status Mount(const VfsPath&, const OsPath&, size_t, size_t) 58 { 59 throw "Not yet implemented"; 60 } 61 62 /** 63 * Retrieve information about a file (similar to POSIX stat). 64 * 65 * @param pathname 66 * @param pfileInfo receives information about the file. Passing NULL 67 * suppresses warnings if the file doesn't exist. 68 * 69 * @return Always OK (any file is faked to exist, and has the content 70 * supplied in the constructor). 71 **/ 72 virtual Status GetFileInfo(const VfsPath& pathname, CFileInfo* pfileInfo) const 73 { 74 if (pfileInfo) 75 { 76 *pfileInfo = CFileInfo(pathname, this->m_FileSize, 0); 77 } 78 return INFO::OK; 79 } 80 81 virtual Status GetFilePriority(const VfsPath&, size_t*) const 82 { 83 throw "Not yet implemented"; 84 } 85 86 virtual Status GetDirectoryEntries(const VfsPath&, CFileInfos*, DirectoryNames*) const 87 { 88 throw "Not yet implemented"; 89 } 90 91 virtual Status CreateFile(const VfsPath&, const shared_ptr<u8>&, size_t) 92 { 93 94 throw "Not yet implemented"; 95 } 96 97 virtual Status ReplaceFile(const VfsPath&, const shared_ptr<u8>&, size_t) 98 { 99 throw "Not yet implemented"; 100 } 101 102 /** 103 * Read an entire file into memory. 104 * 105 * @param fileContents receives a smart pointer to the contents. 106 * CAVEAT: this will be taken from the file cache if the VFS was 107 * created with cacheSize != 0 and size < cacheSize. There is no 108 * provision for Copy-on-Write, which means that such buffers 109 * must not be modified (this is enforced via mprotect). 110 * @param size receives the size [bytes] of the file contents. 111 * @return Status. 112 **/ 113 virtual Status LoadFile(const VfsPath&, shared_ptr<u8>& fileContents, size_t& size) 114 { 115 fileContents = this->m_FileContent; 116 size = this->m_FileSize; 117 return INFO::OK; 118 } 119 120 virtual std::wstring TextRepresentation() const 121 { 122 throw "Not yet implemented"; 123 } 124 125 virtual Status GetRealPath(const VfsPath&, OsPath&) 126 { 127 throw "Not yet implemented"; 128 } 129 130 virtual Status GetDirectoryRealPath(const VfsPath&, OsPath&) 131 { 132 throw "Not yet implemented"; 133 } 134 135 virtual Status GetVirtualPath(const OsPath&, VfsPath&) 136 { 137 throw "Not yet implemented"; 138 } 139 140 virtual Status RemoveFile(const VfsPath&) 141 { 142 throw "Not yet implemented"; 143 } 144 145 virtual Status RepopulateDirectory(const VfsPath&) 146 { 147 throw "Not yet implemented"; 148 } 149 150 virtual void Clear() 151 { 152 throw "Not yet implemented"; 153 } 154 155 private: 156 157 /** 158 * Data found in all "files" of this file system. 159 */ 160 shared_ptr<u8> m_FileContent; 161 162 /** 163 * Number of valid elements in 'm_FileContent' 164 */ 165 const size_t m_FileSize; 166 }; 167 168 } 169 26 170 class TestScriptInterface : public CxxTest::TestSuite 27 171 { 28 172 public: 173 174 void test_loadglobalscriptfile_accepts_rawascii() 175 { 176 PIVFS originalVFS(g_VFS); 177 ScriptInterface script("Test", "Test", ScriptInterface::CreateRuntime()); 178 TestLogger logger; 179 // Small calculation in output so we can see whether script was really 180 // evaluated 181 static const u8 testScript[] = "warn('The key is: ASC' + (4+7));"; 182 183 g_VFS = PIVFS( 184 new test_ScriptInterface::StubVFS( 185 (sizeof(testScript) / sizeof(testScript[0])) - 1, 186 testScript)); 187 188 bool scriptLoaded = script.LoadGlobalScriptFile("test.js"); 189 TS_ASSERT(scriptLoaded); 190 191 std::wstring scriptOutput = logger.GetOutput(); 192 TS_ASSERT_WSTR_CONTAINS(scriptOutput, L"The key is: ASC11"); 193 g_VFS = originalVFS; 194 } 195 196 void test_loadglobalscriptfile_accepts_utf8bom() 197 { 198 PIVFS originalVFS(g_VFS); 199 ScriptInterface script("Test", "Test", ScriptInterface::CreateRuntime()); 200 TestLogger logger; 201 // Small calculation in output so we can see whether script was really 202 // evaluated 203 static const u8 testScript[] = "\xEF\xBB\xBFwarn('The key is: ' + (3 * 5));"; 204 205 g_VFS = PIVFS( 206 new test_ScriptInterface::StubVFS( 207 (sizeof(testScript) / sizeof(testScript[0])) - 1, 208 testScript)); 209 210 bool scriptLoaded = script.LoadGlobalScriptFile("test.js"); 211 TS_ASSERT(scriptLoaded); 212 213 std::wstring scriptOutput = logger.GetOutput(); 214 TS_ASSERT_WSTR_CONTAINS(scriptOutput, L"The key is: 15"); 215 g_VFS = originalVFS; 216 } 217 29 218 void test_loadscript_basic() 30 219 { 31 220 ScriptInterface script("Test", "Test", ScriptInterface::CreateRuntime()); … … 126 315 TS_ASSERT_EQUALS(d1, d2); 127 316 } 128 317 318 void test_readjsonfile_accepts_rawascii() 319 { 320 PIVFS originalVFS(g_VFS); 321 static const u8 jsonCode[] = "{ \"encoding\" : \"plain old text\" }"; 322 g_VFS = PIVFS( 323 new test_ScriptInterface::StubVFS( 324 sizeof(jsonCode) / sizeof(jsonCode[0]) - 1, // don't include \0 at end 325 jsonCode)); 326 327 ScriptInterface script("Test", "Test", ScriptInterface::CreateRuntime()); 328 329 CScriptValRooted jsonData = script.ReadJSONFile("test.json"); 330 jsval actualObj = jsonData.get(); 331 CStr testValue; 332 script.GetProperty(actualObj, "encoding", testValue); 333 334 TS_ASSERT_EQUALS(testValue, "plain old text"); 335 336 g_VFS = originalVFS; 337 } 338 339 void test_readjsonfile_accepts_utf8bom() 340 { 341 PIVFS originalVFS(g_VFS); 342 static const u8 jsonCode[] = "\xEF\xBB\xBF{ \"id\" : \"Herakles\" }"; 343 g_VFS = PIVFS( 344 new test_ScriptInterface::StubVFS( 345 sizeof(jsonCode) / sizeof(jsonCode[0]) - 1, // don't include \0 at end 346 jsonCode)); 347 348 ScriptInterface script("Test", "Test", ScriptInterface::CreateRuntime()); 349 350 CScriptValRooted jsonData = script.ReadJSONFile("test.json"); 351 jsval actualObj = jsonData.get(); 352 CStr testValue; 353 script.GetProperty(actualObj, "id", testValue); 354 355 TS_ASSERT_EQUALS(testValue, "Herakles"); 356 357 g_VFS = originalVFS; 358 } 359 129 360 void test_json() 130 361 { 131 362 ScriptInterface script("Test", "Test", ScriptInterface::CreateRuntime()); -
source/simulation2/Simulation2.h
263 263 */ 264 264 std::string GetAIData(); 265 265 266 protected: 267 // Helper for reading JSON files, protected so 268 // unit tests may access it via inheritance 269 std::string ReadJSON(VfsPath path); 270 266 271 private: 267 272 CSimulation2Impl* m; 268 273 269 // Helper for reading JSON files270 std::string ReadJSON(VfsPath path);271 272 274 NONCOPYABLE(CSimulation2); 273 275 }; 274 276 -
source/simulation2/tests/test_ComponentManager.h
63 63 man.LoadComponentTypes(); 64 64 } 65 65 66 void test_LoadScriptWithUTF8BOMSucceeds() 67 { 68 CSimContext context; 69 CComponentManager man(context, ScriptInterface::CreateRuntime()); 70 71 bool isLoaded = man.LoadScript(L"simulation/components/test-bom-utf8.js"); 72 TS_ASSERT(isLoaded); 73 74 // The script file loaded before adds a new property "Note" to the Engine 75 // object, as a simple proof it was executed at all. 76 ScriptInterface &scripts = man.GetScriptInterface(); 77 78 CScriptVal engine; 79 bool hasEngine = scripts.GetProperty(scripts.GetGlobalObject(), "Engine", engine); 80 81 TS_ASSERT(hasEngine); 82 83 CScriptVal note; 84 bool hasNote = scripts.GetProperty(engine.get(), "Note", note); 85 TS_ASSERT(hasNote); 86 87 std::wstring noteText = scripts.ToString(note.get(), true); 88 TS_ASSERT_EQUALS(noteText, L"\"UTF8-BOM was accepted\""); 89 } 90 91 void test_LoadScriptWithoutBOMSucceeds() 92 { 93 CSimContext context; 94 CComponentManager man(context, ScriptInterface::CreateRuntime()); 95 96 bool isLoaded = man.LoadScript(L"simulation/components/test-bom-none.js"); 97 TS_ASSERT(isLoaded); 98 99 // The script file loaded before adds a new property "Note" to the Engine 100 // object, as a simple proof it was executed at all. 101 ScriptInterface &scripts = man.GetScriptInterface(); 102 103 CScriptVal engine; 104 bool hasEngine = scripts.GetProperty(scripts.GetGlobalObject(), "Engine", engine); 105 106 TS_ASSERT(hasEngine); 107 108 CScriptVal note; 109 bool hasNote = scripts.GetProperty(engine.get(), "Note", note); 110 TS_ASSERT(hasNote); 111 112 std::wstring noteText = scripts.ToString(note.get(), true); 113 114 TS_ASSERT_EQUALS(noteText, L"\"Script without BOM was accepted\""); 115 } 116 66 117 void test_LookupCID() 67 118 { 68 119 CSimContext context; -
source/simulation2/tests/test_Simulation2.h
27 27 #include "ps/Filesystem.h" 28 28 #include "ps/XML/Xeromyces.h" 29 29 30 /** 31 * Helper namespace to hold utility classes for testing of 'Simulation2' 32 * (prevent collision with similary-named stubs for other classes) 33 */ 34 namespace test_Simulation2 35 { 36 37 /** 38 * Lightweight testing implementation of a virtual file system. 39 * 40 * While the TestSimulation2 class already has an associated mod (_test.sim), 41 * testing of the file loader routines via a stub has several advantages: 42 * 1. Some routines, such as GetRMSData(), scan a whole directory whose path is 43 * hard-coded in the testee. Using a real VFS might cause undesired interferences 44 * as more tests are added for a single routine. 45 * 2. A pure in-memory VFS is much faster. 46 * 3. For UTF-8 tests, control characters (such as a leading BOM) may be expressed 47 * directly in the C code, while they might be invisible in some editors when 48 * put in real files. 49 */ 50 struct StubVFS : public IVFS { 51 52 /** 53 * Simulates a file. 54 */ 55 class StubFile 56 { 57 public: 58 59 /** 60 * Initializes a new stub file with fixed content. 61 * @param filename Name of the file. 62 * @param dataLength Size of the data held by the fake file. 63 * @param data Data found in the associated file. 64 */ 65 StubFile(const char filename[], size_t dataLength, const u8 data[]) : 66 m_FileName(filename), 67 m_FileSize(dataLength) 68 { 69 u8 *dataCopy = new u8[dataLength]; 70 memcpy(dataCopy, data, dataLength); 71 this->m_FileContent = shared_ptr<u8>(dataCopy); 72 } 73 74 /** 75 * Provides the data size of the file. 76 * @return An info record with file size and a fake date. 77 */ 78 CFileInfo getInfo() const 79 { 80 return CFileInfo(this->getName(), this->m_FileSize, 0); 81 } 82 83 /** 84 * Retrieves the name of the file. 85 * @return The filename passed into the constructor. 86 */ 87 OsPath getName() const 88 { 89 return OsPath(this->m_FileName); 90 } 91 92 /** 93 * Retrieves the data of this file. 94 * @return A copy of the data passed to the constructor. 95 */ 96 shared_ptr<u8> getContent() const 97 { 98 return this->m_FileContent; 99 } 100 101 private: 102 103 /** 104 * Name of this file. 105 */ 106 const char *m_FileName; 107 108 /** 109 * Data found in the file represented by this object 110 */ 111 shared_ptr<u8> m_FileContent; 112 113 /** 114 * Data size of 'm_FileContent' 115 */ 116 const size_t m_FileSize; 117 }; 118 119 /** 120 * Creates a stub file system which simulates a fixed set of files. 121 * @param numberOfFiles Number of valid entries in 'files'. 122 * @param files The files which are provided (no real support for 123 * directories, all files are returned on each call to 124 * 'GetDirectoryEntries'). 125 */ 126 StubVFS(size_t numberOfFiles, const StubFile files[]) : 127 m_NumberOfFiles(numberOfFiles) 128 { 129 this->m_Files = files; 130 } 131 132 virtual Status Mount(const VfsPath&, const OsPath&, size_t, size_t) 133 { 134 throw "Not yet implemented"; 135 } 136 137 virtual Status GetFileInfo(const VfsPath& path, CFileInfo* info) const 138 { 139 for (size_t i = 0; i < this->m_NumberOfFiles; i++) 140 { 141 if (this->m_Files[i].getName() == path.Filename()) 142 { 143 if (info) 144 { 145 *info = this->m_Files[i].getInfo(); 146 } 147 return INFO::OK; 148 } 149 } 150 return CODE__PSRETURN_Scripting_LoadFile_OpenFailed; 151 } 152 153 virtual Status GetFilePriority(const VfsPath&, size_t*) const 154 { 155 throw "Not yet implemented"; 156 } 157 158 /** 159 * Retrieves a listing of all files held by this file system. 160 * @param infos Receives additional information about a file. 161 * @param names Receives the names of all files in the file system. 162 * @return OK. 163 */ 164 virtual Status GetDirectoryEntries(const VfsPath&, CFileInfos* infos, DirectoryNames* names) const 165 { 166 for (size_t i = 0; i < this->m_NumberOfFiles; i++) 167 { 168 if (infos) 169 { 170 infos->push_back(this->m_Files[i].getInfo()); 171 } 172 if (names) 173 { 174 names->push_back(this->m_Files[i].getName()); 175 } 176 } 177 return INFO::OK; 178 } 179 180 virtual Status CreateFile(const VfsPath&, const shared_ptr<u8>&, size_t) 181 { 182 183 throw "Not yet implemented"; 184 } 185 186 virtual Status ReplaceFile(const VfsPath&, const shared_ptr<u8>&, size_t) 187 { 188 throw "Not yet implemented"; 189 } 190 191 /** 192 * Read an entire file into memory. 193 * 194 * @param path Selects the fake file whose content is requested. 195 * @param fileContents receives a smart pointer to the contents. 196 * CAVEAT: this will be taken from the file cache if the VFS was 197 * created with cacheSize != 0 and size < cacheSize. There is no 198 * provision for Copy-on-Write, which means that such buffers 199 * must not be modified (this is enforced via mprotect). 200 * @param size receives the size [bytes] of the file contents. 201 * @return OK, if a fake file with given path was selected, or 202 * OpenFailed in case the file does not exist. 203 **/ 204 virtual Status LoadFile(const VfsPath& path, shared_ptr<u8>& fileContents, size_t& size) 205 { 206 for (size_t i = 0; i < this->m_NumberOfFiles; i++) 207 { 208 if (this->m_Files[i].getName() == path.Filename()) 209 { 210 fileContents = this->m_Files[i].getContent(); 211 size = this->m_Files[i].getInfo().Size(); 212 return INFO::OK; 213 } 214 } 215 return CODE__PSRETURN_Scripting_LoadFile_OpenFailed; 216 } 217 218 virtual std::wstring TextRepresentation() const 219 { 220 throw "Not yet implemented"; 221 } 222 223 virtual Status GetRealPath(const VfsPath&, OsPath&) 224 { 225 throw "Not yet implemented"; 226 } 227 228 virtual Status GetDirectoryRealPath(const VfsPath&, OsPath&) 229 { 230 throw "Not yet implemented"; 231 } 232 233 virtual Status GetVirtualPath(const OsPath&, VfsPath&) 234 { 235 throw "Not yet implemented"; 236 } 237 238 /** 239 * remove file from the virtual directory listing and evict its 240 * data from the cache. 241 **/ 242 virtual Status RemoveFile(const VfsPath&) 243 { 244 throw "Not yet implemented"; 245 } 246 247 virtual Status RepopulateDirectory(const VfsPath&) 248 { 249 throw "Not yet implemented"; 250 } 251 252 virtual void Clear() 253 { 254 throw "Not yet implemented"; 255 } 256 257 private: 258 259 /** 260 * Number of valid elements in 'm_Files'. 261 */ 262 const size_t m_NumberOfFiles; 263 264 /** 265 * The files found in this file system. 266 */ 267 const StubFile *m_Files; 268 }; 269 270 } 271 30 272 class TestSimulation2 : public CxxTest::TestSuite 31 273 { 32 274 void copyFile(const VfsPath& src, const VfsPath& dst) … … 39 281 40 282 CTerrain m_Terrain; 41 283 284 /** 285 * Provides access to CSimulation2::ReadJSON() via inheritance 286 */ 287 class CSimulation2Hook : public CSimulation2 288 { 289 public: 290 CSimulation2Hook(CUnitManager* unitManager, shared_ptr<ScriptRuntime> rt, CTerrain* terrain) : 291 CSimulation2(unitManager, rt, terrain) 292 { 293 } 294 295 std::string ReadJSON(VfsPath path) 296 { 297 return CSimulation2::ReadJSON(path); 298 } 299 }; 300 301 42 302 public: 43 303 void setUp() 44 304 { … … 127 387 sim.BroadcastMessage(msg); 128 388 } 129 389 390 /** 391 * Civ data files shall be loaded with utf8 byte-order-mark suppressed, if present. 392 */ 393 void test_getcivdata_utf8support() 394 { 395 const u8 content1[] = "\xEF\xBB\xBF Asian characters"; 396 const u8 content2[] = "}:-) wikings"; 397 test_Simulation2::StubVFS::StubFile testFiles[] = 398 { // Note: "- 1" suppresses the terminating \0 from the "file data" 399 test_Simulation2::StubVFS::StubFile("asian.json", sizeof(content1)/sizeof(content1[0]) - 1, content1), 400 test_Simulation2::StubVFS::StubFile("wikings.json", sizeof(content2)/sizeof(content2[0]) - 1, content2) 401 }; 402 403 PIVFS originalVFS(g_VFS); 404 g_VFS = PIVFS(new test_Simulation2::StubVFS(sizeof(testFiles)/sizeof(testFiles[0]), testFiles)); 405 406 CSimulation2 sim(NULL, ScriptInterface::CreateRuntime(), &m_Terrain); 407 408 std::vector<std::string> civData = sim.GetCivData(); 409 410 size_t numberOfCivs = civData.size(); 411 TS_ASSERT_EQUALS(numberOfCivs, 2); 412 413 if (2 == numberOfCivs) // Prevent OutOfRange exception in case of failure 414 { 415 TS_ASSERT_EQUALS(civData[0], " Asian characters"); 416 TS_ASSERT_EQUALS(civData[1], "}:-) wikings"); 417 } 418 419 g_VFS = originalVFS; 420 } 421 422 /** 423 * Random map scripts/data shall be loaded with proper utf8 byte-order-mark 424 * support. 425 */ 426 void test_getrmsdata_utf8support() 427 { 428 const u8 content1[] = "Maritime terrain <.))><"; 429 const u8 content2[] = "\xEF\xBB\xBF Exotic language"; 430 test_Simulation2::StubVFS::StubFile testFiles[] = 431 { // Note: "- 1" suppresses the terminating \0 from the "file data" 432 test_Simulation2::StubVFS::StubFile("script1.json", sizeof(content1)/sizeof(content1[0]) - 1, content1), 433 test_Simulation2::StubVFS::StubFile("script2.json", sizeof(content2)/sizeof(content2[0]) - 1, content2) 434 }; 435 436 PIVFS originalVFS(g_VFS); 437 g_VFS = PIVFS(new test_Simulation2::StubVFS(sizeof(testFiles)/sizeof(testFiles[0]), testFiles)); 438 439 CSimulation2 sim(NULL, ScriptInterface::CreateRuntime(), &m_Terrain); 440 441 std::vector<std::string> RMSScripts = sim.GetRMSData(); 442 443 size_t numberOfScripts = RMSScripts.size(); 444 TS_ASSERT_EQUALS(numberOfScripts, 2); 445 446 if (2 == numberOfScripts) // Prevent OutOfRange exception in case of failure 447 { 448 TS_ASSERT_EQUALS(RMSScripts[0], "Maritime terrain <.))><"); 449 TS_ASSERT_EQUALS(RMSScripts[1], " Exotic language"); 450 } 451 452 g_VFS = originalVFS; 453 } 454 130 455 void test_hotload_scripts() 131 456 { 132 457 CSimulation2 sim(NULL, ScriptInterface::CreateRuntime(), &m_Terrain); … … 164 489 165 490 TS_ASSERT_OK(sim.ReloadChangedFile(L"simulation/components/hotload/hotload.js")); 166 491 } 492 493 void test_readjson_asciifilessupported() 494 { 495 const u8 content[] = "\xEF\xBB\xBF{id:'Raw data'}"; 496 test_Simulation2::StubVFS::StubFile testFiles[] = 497 { // Note: "- 1" suppresses the terminating \0 from the "file data" 498 test_Simulation2::StubVFS::StubFile("script.json", sizeof(content)/sizeof(content[0]) - 1, content) 499 }; 500 501 PIVFS originalVFS(g_VFS); 502 g_VFS = PIVFS(new test_Simulation2::StubVFS(sizeof(testFiles)/sizeof(testFiles[0]), testFiles)); 503 504 CSimulation2Hook sim(NULL, ScriptInterface::CreateRuntime(), &m_Terrain); 505 506 std::string result = sim.ReadJSON("script.json"); 507 508 TS_ASSERT_EQUALS(result, "{id:'Raw data'}"); 509 510 g_VFS = originalVFS; 511 } 512 513 void test_readjson_utf8bomsupported() 514 { 515 const u8 content[] = "\xEF\xBB\xBF{id:'Blah'}"; 516 test_Simulation2::StubVFS::StubFile testFiles[] = 517 { // Note: "- 1" suppresses the terminating \0 from the "file data" 518 test_Simulation2::StubVFS::StubFile("script.json", sizeof(content)/sizeof(content[0]) - 1, content) 519 }; 520 521 PIVFS originalVFS(g_VFS); 522 g_VFS = PIVFS(new test_Simulation2::StubVFS(sizeof(testFiles)/sizeof(testFiles[0]), testFiles)); 523 524 CSimulation2Hook sim(NULL, ScriptInterface::CreateRuntime(), &m_Terrain); 525 526 std::string result = sim.ReadJSON("script.json"); 527 528 TS_ASSERT_EQUALS(result, "{id:'Blah'}"); 529 530 g_VFS = originalVFS; 531 } 532 167 533 };