def testCoreProject_LockFile(monkeypatch, fncDir, mockGUI): """Test lock file functions for the project folder. """ theProject = NWProject(mockGUI) lockFile = os.path.join(fncDir, nwFiles.PROJ_LOCK) # No project assert theProject._writeLockFile() is False assert theProject._readLockFile() == ["ERROR"] assert theProject._clearLockFile() is False theProject.projPath = fncDir theProject.mainConf.hostName = "TestHost" theProject.mainConf.osType = "TestOS" theProject.mainConf.kernelVer = "1.0" # Block open with monkeypatch.context() as mp: mp.setattr("builtins.open", causeOSError) assert theProject._writeLockFile() is False # Write lock file with monkeypatch.context() as mp: mp.setattr("novelwriter.core.project.time", lambda: 123.4) assert theProject._writeLockFile() is True assert readFile(lockFile) == "TestHost\nTestOS\n1.0\n123\n" # Block open with monkeypatch.context() as mp: mp.setattr("builtins.open", causeOSError) assert theProject._readLockFile() == ["ERROR"] # Read lock file assert theProject._readLockFile() == ["TestHost", "TestOS", "1.0", "123"] # Block unlink with monkeypatch.context() as mp: mp.setattr("os.unlink", causeOSError) assert os.path.isfile(lockFile) assert theProject._clearLockFile() is False assert os.path.isfile(lockFile) # Clear file assert os.path.isfile(lockFile) assert theProject._clearLockFile() is True assert not os.path.isfile(lockFile) # Read again, no file assert theProject._readLockFile() == [] # Read an invalid lock file writeFile(lockFile, "A\nB") assert theProject._readLockFile() == ["ERROR"] assert theProject._clearLockFile() is True
def testCoreProject_Open(monkeypatch, nwMinimal, mockGUI): """Test opening a project. """ theProject = NWProject(mockGUI) # Rename the project file to check handling rName = os.path.join(nwMinimal, nwFiles.PROJ_FILE) wName = os.path.join(nwMinimal, nwFiles.PROJ_FILE + "_sdfghj") os.rename(rName, wName) assert theProject.openProject(nwMinimal) is False os.rename(wName, rName) # Fail on folder structure check with monkeypatch.context() as mp: mp.setattr("os.mkdir", causeOSError) assert theProject.openProject(nwMinimal) is False # Fail on lock file theProject.setProjectPath(nwMinimal) assert theProject._writeLockFile() assert theProject.openProject(nwMinimal) is False # Fail to read lockfile (which still opens the project) with monkeypatch.context() as mp: mp.setattr("builtins.open", causeOSError) assert theProject.openProject(nwMinimal) is True assert theProject.closeProject() # Force open with lockfile theProject.setProjectPath(nwMinimal) assert theProject._writeLockFile() assert theProject.openProject(nwMinimal, overrideLock=True) is True assert theProject.closeProject() # Make a junk XML file oName = os.path.join(nwMinimal, nwFiles.PROJ_FILE[:-3] + "orig") bName = os.path.join(nwMinimal, nwFiles.PROJ_FILE[:-3] + "bak") os.rename(rName, oName) writeFile(rName, "stuff") assert theProject.openProject(nwMinimal) is False # Also write a jun XML backup file writeFile(bName, "stuff") assert theProject.openProject(nwMinimal) is False # Wrong root item writeFile(rName, "<not_novelWriterXML></not_novelWriterXML>\n") assert theProject.openProject(nwMinimal) is False # Wrong file version writeFile(rName, ("<?xml version='0.0' encoding='utf-8'?>\n" "<novelWriterXML " "appVersion=\"1.0\" " "hexVersion=\"0x01000000\" " "fileVersion=\"1.0\" " "timeStamp=\"2020-01-01 00:00:00\">\n" "</novelWriterXML>\n")) mockGUI.askResponse = False assert theProject.openProject(nwMinimal) is False mockGUI.undo() # Future file version writeFile(rName, ("<?xml version='1.0' encoding='utf-8'?>\n" "<novelWriterXML " "appVersion=\"1.0\" " "hexVersion=\"0x01000000\" " "fileVersion=\"99.99\" " "timeStamp=\"2020-01-01 00:00:00\">\n" "</novelWriterXML>\n")) assert theProject.openProject(nwMinimal) is False # Update file version writeFile(rName, ("<?xml version='1.0' encoding='utf-8'?>\n" "<novelWriterXML " "appVersion=\"1.0\" " "hexVersion=\"0xffffffff\" " "fileVersion=\"1.2\" " "timeStamp=\"2020-01-01 00:00:00\">\n" "</novelWriterXML>\n")) mockGUI.askResponse = False assert theProject.openProject(nwMinimal) is False assert mockGUI.lastQuestion[0] == "File Version" mockGUI.undo() # Larger hex version writeFile(rName, ("<?xml version='1.0' encoding='utf-8'?>\n" "<novelWriterXML " "appVersion=\"1.0\" " "hexVersion=\"0xffffffff\" " "fileVersion=\"%s\" " "timeStamp=\"2020-01-01 00:00:00\">\n" "</novelWriterXML>\n") % theProject.FILE_VERSION) mockGUI.askResponse = False assert theProject.openProject(nwMinimal) is False assert mockGUI.lastQuestion[0] == "Version Conflict" mockGUI.undo() # Test skipping XML entries writeFile(rName, ("<?xml version='1.0' encoding='utf-8'?>\n" "<novelWriterXML " "appVersion=\"1.0\" " "hexVersion=\"0x01000000\" " "fileVersion=\"1.2\" " "timeStamp=\"2020-01-01 00:00:00\">\n" "<project><stuff/></project>\n" "<settings><stuff/></settings>\n" "</novelWriterXML>\n")) assert theProject.openProject(nwMinimal) is True assert theProject.closeProject() # Clean up XML files os.unlink(rName) os.unlink(bName) os.rename(oName, rName) # Add some legacy stuff that cannot be removed writeFile(os.path.join(nwMinimal, "junk"), "stuff") os.mkdir(os.path.join(nwMinimal, "data_0")) writeFile(os.path.join(nwMinimal, "data_0", "junk"), "stuff") mockGUI.clear() assert theProject.openProject(nwMinimal) is True assert "data_0" in mockGUI.lastAlert assert theProject.closeProject()