Perform a detailed check of the loaded index to make sure everything is in order
This commit is contained in:
+159
-25
@@ -36,11 +36,13 @@ from nw.constants import (
|
||||
)
|
||||
from nw.core.document import NWDoc
|
||||
from nw.core.tools import countWords
|
||||
from nw.common import isHandle, isTitleTag, isItemClass, isItemLayout
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class NWIndex():
|
||||
|
||||
H_VALID = ("H0", "H1", "H2", "H3", "H4")
|
||||
H_LEVEL = {"H0": 0, "H1": 1, "H2": 2, "H3": 3, "H4": 4}
|
||||
|
||||
def __init__(self, theProject, theParent):
|
||||
@@ -155,6 +157,11 @@ class NWIndex():
|
||||
except Exception as e:
|
||||
logger.error("Failed to load index file")
|
||||
logger.error(str(e))
|
||||
self.indexBroken = True
|
||||
self.theParent.makeAlert(
|
||||
"Could not load cached index file. Rebuilding index.",
|
||||
nwAlert.WARN
|
||||
)
|
||||
return False
|
||||
|
||||
self._tagIndex = theData.get("tagIndex", {})
|
||||
@@ -200,37 +207,25 @@ class NWIndex():
|
||||
elements it should.
|
||||
"""
|
||||
logger.debug("Checking index")
|
||||
self.indexBroken = False
|
||||
tStart = time()
|
||||
|
||||
try:
|
||||
for tTag in self._tagIndex:
|
||||
if len(self._tagIndex[tTag]) != 4:
|
||||
self.indexBroken = True
|
||||
self._checkTagIndex()
|
||||
self._checkRefIndex()
|
||||
self._checkNovelNoteIndex("novelIndex")
|
||||
self._checkNovelNoteIndex("noteIndex")
|
||||
self._checkTextCounts()
|
||||
self.indexBroken = False
|
||||
|
||||
for tHandle in self._refIndex:
|
||||
for sTitle in self._refIndex[tHandle]:
|
||||
for tEntry in self._refIndex[tHandle][sTitle]["tags"]:
|
||||
if len(tEntry) != 3:
|
||||
self.indexBroken = True
|
||||
|
||||
for tHandle in self._novelIndex:
|
||||
for sLine in self._novelIndex[tHandle]:
|
||||
if len(self._novelIndex[tHandle][sLine].keys()) != 8:
|
||||
self.indexBroken = True
|
||||
|
||||
for tHandle in self._noteIndex:
|
||||
for sLine in self._noteIndex[tHandle]:
|
||||
if len(self._noteIndex[tHandle][sLine].keys()) != 8:
|
||||
self.indexBroken = True
|
||||
|
||||
for tHandle in self._textCounts:
|
||||
if len(self._textCounts[tHandle]) != 3:
|
||||
self.indexBroken = True
|
||||
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
logger.error("Error while checking index")
|
||||
nw.logException(e)
|
||||
self.indexBroken = True
|
||||
|
||||
tEnd = time()
|
||||
logger.debug("Index check took %.3f ms" % ((tEnd - tStart)*1000))
|
||||
logger.debug("Index check complete")
|
||||
|
||||
if self.indexBroken:
|
||||
self.clearIndex()
|
||||
self.theParent.makeAlert(
|
||||
@@ -745,4 +740,143 @@ class NWIndex():
|
||||
|
||||
return theHandles
|
||||
|
||||
##
|
||||
# Index Checkers
|
||||
##
|
||||
|
||||
def _checkTagIndex(self):
|
||||
"""Scan the tag index for errors.
|
||||
Waring: This function raises exceptions.
|
||||
"""
|
||||
for tTag in self._tagIndex:
|
||||
if not isinstance(tTag, str):
|
||||
raise KeyError("tagIndex key is not a string")
|
||||
|
||||
tEntry = self._tagIndex[tTag]
|
||||
if len(tEntry) != 4:
|
||||
raise IndexError("tagIndex[a] expected 4 values")
|
||||
if not isinstance(tEntry[0], int):
|
||||
raise ValueError("tagIndex[a][0] is not an integer")
|
||||
if not isHandle(tEntry[1]):
|
||||
raise ValueError("tagIndex[a][1] is not a handle")
|
||||
if not isItemClass(tEntry[2]):
|
||||
raise ValueError("tagIndex[a][2] is not an nwItemClass")
|
||||
if not isTitleTag(tEntry[3]):
|
||||
raise ValueError("tagIndex[a][3] is not a title tag")
|
||||
|
||||
return
|
||||
|
||||
def _checkRefIndex(self):
|
||||
"""Scan the reference index for errors.
|
||||
Waring: This function raises exceptions.
|
||||
"""
|
||||
for tHandle in self._refIndex:
|
||||
if not isHandle(tHandle):
|
||||
raise KeyError("refIndex key is not a handle")
|
||||
|
||||
hEntry = self._refIndex[tHandle]
|
||||
for sTitle in hEntry:
|
||||
if not isTitleTag(sTitle):
|
||||
raise KeyError("refIndex[a] key is not a title tag")
|
||||
|
||||
sEntry = hEntry[sTitle]
|
||||
if "tags" not in sEntry:
|
||||
raise KeyError("refIndex[a][b] has no 'tag' key")
|
||||
for tEntry in sEntry["tags"]:
|
||||
if len(tEntry) != 3:
|
||||
raise IndexError("refIndex[a][b][tags][i] expected 3 values")
|
||||
if not isinstance(tEntry[0], int):
|
||||
raise ValueError("refIndex[a][b][tags][i][0] is not an integer")
|
||||
if not tEntry[1] in nwKeyWords.VALID_KEYS:
|
||||
raise ValueError("refIndex[a][b][tags][i][1] is not a keyword")
|
||||
if not isinstance(tEntry[2], str):
|
||||
raise ValueError("refIndex[a][b][tags][i][2] is not a string")
|
||||
|
||||
if "updated" not in sEntry:
|
||||
raise KeyError("refIndex[a][b] has no 'updated' key")
|
||||
if not isinstance(sEntry["updated"], int):
|
||||
raise ValueError("%refIndex[a][b][updated] is not an integer")
|
||||
|
||||
return
|
||||
|
||||
def _checkNovelNoteIndex(self, idxName):
|
||||
"""Scan the novel or note index for errors.
|
||||
Waring: This function raises exceptions.
|
||||
"""
|
||||
if idxName == "novelIndex":
|
||||
theIndex = self._novelIndex
|
||||
elif idxName == "noteIndex":
|
||||
theIndex = self._noteIndex
|
||||
else:
|
||||
raise IndexError("Unknown index %s" % idxName)
|
||||
|
||||
for tHandle in theIndex:
|
||||
if not isHandle(tHandle):
|
||||
raise KeyError("%s key is not a handle" % idxName)
|
||||
|
||||
hEntry = theIndex[tHandle]
|
||||
for sTitle in theIndex[tHandle]:
|
||||
if not isTitleTag(sTitle):
|
||||
raise KeyError("%s[a] key is not a title tag" % idxName)
|
||||
|
||||
sEntry = hEntry[sTitle]
|
||||
if len(sEntry) != 8:
|
||||
raise IndexError("%s[a][b] expected 8 values" % idxName)
|
||||
|
||||
if "level" not in sEntry:
|
||||
raise KeyError("%s[a][b] has no 'level' key" % idxName)
|
||||
if "title" not in sEntry:
|
||||
raise KeyError("%s[a][b] has no 'title' key" % idxName)
|
||||
if "layout" not in sEntry:
|
||||
raise KeyError("%s[a][b] has no 'layout' key" % idxName)
|
||||
if "synopsis" not in sEntry:
|
||||
raise KeyError("%s[a][b] has no 'synopsis' key" % idxName)
|
||||
if "cCount" not in sEntry:
|
||||
raise KeyError("%s[a][b] has no 'cCount' key" % idxName)
|
||||
if "wCount" not in sEntry:
|
||||
raise KeyError("%s[a][b] has no 'wCount' key" % idxName)
|
||||
if "pCount" not in sEntry:
|
||||
raise KeyError("%s[a][b] has no 'pCount' key" % idxName)
|
||||
if "updated" not in sEntry:
|
||||
raise KeyError("%s[a][b] has no 'updated' key" % idxName)
|
||||
|
||||
if not sEntry["level"] in self.H_VALID:
|
||||
raise ValueError("%s[a][b][level] is not a header level" % idxName)
|
||||
if not isinstance(sEntry["title"], str):
|
||||
raise ValueError("%s[a][b][title] is not a string" % idxName)
|
||||
if not isItemLayout(sEntry["layout"]):
|
||||
raise ValueError("%s[a][b][layout] is not an nwItemLayout" % idxName)
|
||||
if not isinstance(sEntry["synopsis"], str):
|
||||
raise ValueError("%s[a][b][synopsis] is not a string" % idxName)
|
||||
if not isinstance(sEntry["cCount"], int):
|
||||
raise ValueError("%s[a][b][cCount] is not an integer" % idxName)
|
||||
if not isinstance(sEntry["wCount"], int):
|
||||
raise ValueError("%s[a][b][wCount] is not an integer" % idxName)
|
||||
if not isinstance(sEntry["pCount"], int):
|
||||
raise ValueError("%s[a][b][pCount] is not an integer" % idxName)
|
||||
if not isinstance(sEntry["updated"], int):
|
||||
raise ValueError("%s[a][b][updated] is not an integer" % idxName)
|
||||
|
||||
return
|
||||
|
||||
def _checkTextCounts(self):
|
||||
"""Scan the text counts index for errors.
|
||||
Waring: This function raises exceptions.
|
||||
"""
|
||||
for tHandle in self._textCounts:
|
||||
if not isHandle(tHandle):
|
||||
raise KeyError("textCounts key is not a handle")
|
||||
|
||||
tEntry = self._textCounts[tHandle]
|
||||
if len(tEntry) != 3:
|
||||
raise IndexError("textCounts[a] expected 3 values")
|
||||
if not isinstance(tEntry[0], int):
|
||||
raise ValueError("textCounts[a][0] is not an integer")
|
||||
if not isinstance(tEntry[1], int):
|
||||
raise ValueError("textCounts[a][1] is not an integer")
|
||||
if not isinstance(tEntry[2], int):
|
||||
raise ValueError("textCounts[a][2] is not an integer")
|
||||
|
||||
return
|
||||
|
||||
# END Class NWIndex
|
||||
|
||||
@@ -115,38 +115,7 @@ def testCoreIndex_LoadSave(monkeypatch, nwLipsum, dummyGUI, outDir, refDir):
|
||||
|
||||
# Break the index and check that we notice
|
||||
assert not theIndex.indexBroken
|
||||
theIndex._tagIndex["Bod"].append("Stuff") # No longer len() == 4
|
||||
theIndex.checkIndex()
|
||||
assert theIndex.indexBroken
|
||||
|
||||
assert theIndex.loadIndex()
|
||||
assert not theIndex.indexBroken
|
||||
theIndex._refIndex["fb609cd8319dc"]["T000001"]["tags"].append("Stuff") # No longer len() == 3
|
||||
theIndex.checkIndex()
|
||||
assert theIndex.indexBroken
|
||||
|
||||
assert theIndex.loadIndex()
|
||||
assert not theIndex.indexBroken
|
||||
theIndex._novelIndex["7a992350f3eb6"]["T000001"]["Stuff"] = "" # No longer len(keys()) == 8
|
||||
theIndex.checkIndex()
|
||||
assert theIndex.indexBroken
|
||||
|
||||
assert theIndex.loadIndex()
|
||||
assert not theIndex.indexBroken
|
||||
theIndex._noteIndex["4c4f28287af27"]["T000001"]["Stuff"] = "" # No longer len(keys()) == 8
|
||||
theIndex.checkIndex()
|
||||
assert theIndex.indexBroken
|
||||
|
||||
assert theIndex.loadIndex()
|
||||
assert not theIndex.indexBroken
|
||||
theIndex._textCounts["7a992350f3eb6"].append("Stuff") # No longer len() == 3
|
||||
theIndex.checkIndex()
|
||||
assert theIndex.indexBroken
|
||||
|
||||
# Make the try/except trigger as well
|
||||
assert theIndex.loadIndex()
|
||||
assert not theIndex.indexBroken
|
||||
theIndex._refIndex["fb609cd8319dc"]["T000001"] = {"tagssss": []} # Wrong key name
|
||||
theIndex._tagIndex["Bod"].append("Stuff")
|
||||
theIndex.checkIndex()
|
||||
assert theIndex.indexBroken
|
||||
|
||||
@@ -676,3 +645,503 @@ def testCoreIndex_ExtractData(nwMinimal, dummyGUI):
|
||||
assert theProject.closeProject()
|
||||
|
||||
# END Test testCoreIndex_ExtractData
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreIndex_CheckTagIndex(dummyGUI):
|
||||
"""Test the tag index checker.
|
||||
"""
|
||||
theProject = NWProject(dummyGUI)
|
||||
theIndex = NWIndex(theProject, dummyGUI)
|
||||
|
||||
# Valid Index
|
||||
theIndex._tagIndex = {
|
||||
"John": [3, "14298de4d9524", "CHARACTER", "T000001"],
|
||||
"Jane": [3, "bb2c23b3c42cc", "CHARACTER", "T000001"],
|
||||
}
|
||||
assert theIndex._checkTagIndex() is None
|
||||
|
||||
# Wrong Key Type
|
||||
theIndex._tagIndex = {
|
||||
"John": [3, "14298de4d9524", "CHARACTER", "T000001"],
|
||||
123456: [3, "bb2c23b3c42cc", "CHARACTER", "T000001"],
|
||||
}
|
||||
with pytest.raises(KeyError):
|
||||
theIndex._checkTagIndex()
|
||||
|
||||
# Wrong Length
|
||||
theIndex._tagIndex = {
|
||||
"John": [3, "14298de4d9524", "CHARACTER", "T000001"],
|
||||
"Jane": [3, "bb2c23b3c42cc", "CHARACTER", "T000001", "Stuff"],
|
||||
}
|
||||
with pytest.raises(IndexError):
|
||||
theIndex._checkTagIndex()
|
||||
|
||||
# Wrong Type of Entry 0
|
||||
theIndex._tagIndex = {
|
||||
"John": [3, "14298de4d9524", "CHARACTER", "T000001"],
|
||||
"Jane": ["3", "bb2c23b3c42cc", "CHARACTER", "T000001"],
|
||||
}
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkTagIndex()
|
||||
|
||||
# Wrong Type of Entry 1
|
||||
theIndex._tagIndex = {
|
||||
"John": [3, "14298de4d9524", "CHARACTER", "T000001"],
|
||||
"Jane": [3, 0xbb2c23b3c42cc, "CHARACTER", "T000001"],
|
||||
}
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkTagIndex()
|
||||
|
||||
# Wrong Type of Entry 2
|
||||
theIndex._tagIndex = {
|
||||
"John": [3, "14298de4d9524", "CHARACTER", "T000001"],
|
||||
"Jane": [3, "bb2c23b3c42cc", "INVALID_CLASS", "T000001"],
|
||||
}
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkTagIndex()
|
||||
|
||||
# Wrong Type of Entry 3
|
||||
theIndex._tagIndex = {
|
||||
"John": [3, "14298de4d9524", "CHARACTER", "T000001"],
|
||||
"Jane": [3, "bb2c23b3c42cc", "CHARACTER", "INVALID"],
|
||||
}
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkTagIndex()
|
||||
|
||||
# END Test testCoreIndex_CheckTagIndex
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreIndex_CheckRefIndex(dummyGUI):
|
||||
"""Test the reference index checker.
|
||||
"""
|
||||
theProject = NWProject(dummyGUI)
|
||||
theIndex = NWIndex(theProject, dummyGUI)
|
||||
|
||||
# Valid Index
|
||||
theIndex._refIndex = {
|
||||
"6a2d6d5f4f401": {
|
||||
"T000000": {"tags": [], "updated": 1611922868},
|
||||
"T000001": {"tags": [
|
||||
[3, "@pov", "Jane"], [4, "@location", "Earth"]
|
||||
], "updated": 1611922868}
|
||||
}
|
||||
}
|
||||
assert theIndex._checkRefIndex() is None
|
||||
|
||||
# Invalid Handle
|
||||
theIndex._refIndex = {
|
||||
"Ha2d6d5f4f401": {
|
||||
"T000000": {"tags": [], "updated": 1611922868},
|
||||
"T000001": {"tags": [
|
||||
[3, "@pov", "Jane"], [4, "@location", "Earth"]
|
||||
], "updated": 1611922868}
|
||||
}
|
||||
}
|
||||
with pytest.raises(KeyError):
|
||||
theIndex._checkRefIndex()
|
||||
|
||||
# Invalid Title
|
||||
theIndex._refIndex = {
|
||||
"6a2d6d5f4f401": {
|
||||
"T000000": {"tags": [], "updated": 1611922868},
|
||||
"INVALID": {"tags": [
|
||||
[3, "@pov", "Jane"], [4, "@location", "Earth"]
|
||||
], "updated": 1611922868}
|
||||
}
|
||||
}
|
||||
with pytest.raises(KeyError):
|
||||
theIndex._checkRefIndex()
|
||||
|
||||
# Missing 'tags'
|
||||
theIndex._refIndex = {
|
||||
"6a2d6d5f4f401": {
|
||||
"T000000": {"tags": [], "updated": 1611922868},
|
||||
"T000001": {"updated": 1611922868}
|
||||
}
|
||||
}
|
||||
with pytest.raises(KeyError):
|
||||
theIndex._checkRefIndex()
|
||||
|
||||
# Wrong Length of 'tags'
|
||||
theIndex._refIndex = {
|
||||
"6a2d6d5f4f401": {
|
||||
"T000000": {"tags": [], "updated": 1611922868},
|
||||
"T000001": {"tags": [
|
||||
[3, "@pov", "Jane"], [4, "@location", "Earth", "Stuff"]
|
||||
], "updated": 1611922868}
|
||||
}
|
||||
}
|
||||
with pytest.raises(IndexError):
|
||||
theIndex._checkRefIndex()
|
||||
|
||||
# Wrong Type of 'tags' Entry 0
|
||||
theIndex._refIndex = {
|
||||
"6a2d6d5f4f401": {
|
||||
"T000000": {"tags": [], "updated": 1611922868},
|
||||
"T000001": {"tags": [
|
||||
[3, "@pov", "Jane"], ["4", "@location", "Earth"]
|
||||
], "updated": 1611922868}
|
||||
}
|
||||
}
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkRefIndex()
|
||||
|
||||
# Wrong Type of 'tags' Entry 1
|
||||
theIndex._refIndex = {
|
||||
"6a2d6d5f4f401": {
|
||||
"T000000": {"tags": [], "updated": 1611922868},
|
||||
"T000001": {"tags": [
|
||||
[3, "@pov", "Jane"], [4, "@stuff", "Earth"]
|
||||
], "updated": 1611922868}
|
||||
}
|
||||
}
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkRefIndex()
|
||||
|
||||
# Wrong Type of 'tags' Entry 1
|
||||
theIndex._refIndex = {
|
||||
"6a2d6d5f4f401": {
|
||||
"T000000": {"tags": [], "updated": 1611922868},
|
||||
"T000001": {"tags": [
|
||||
[3, "@pov", "Jane"], [4, "@location", 123456]
|
||||
], "updated": 1611922868}
|
||||
}
|
||||
}
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkRefIndex()
|
||||
|
||||
# Missing 'updated'
|
||||
theIndex._refIndex = {
|
||||
"6a2d6d5f4f401": {
|
||||
"T000000": {"tags": [], "updated": 1611922868},
|
||||
"T000001": {"tags": []}
|
||||
}
|
||||
}
|
||||
with pytest.raises(KeyError):
|
||||
theIndex._checkRefIndex()
|
||||
|
||||
# Wrong Type of 'updated' Entry 1
|
||||
theIndex._refIndex = {
|
||||
"6a2d6d5f4f401": {
|
||||
"T000000": {"tags": [], "updated": 1611922868},
|
||||
"T000001": {"tags": [], "updated": "1611922868"}
|
||||
}
|
||||
}
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkRefIndex()
|
||||
|
||||
# END Test testCoreIndex_CheckRefIndex
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreIndex_CheckNovelNoteIndex(dummyGUI):
|
||||
"""Test the novel and note index checkers.
|
||||
"""
|
||||
theProject = NWProject(dummyGUI)
|
||||
theIndex = NWIndex(theProject, dummyGUI)
|
||||
|
||||
# Valid Index
|
||||
theIndex._novelIndex = {
|
||||
"53b69b83cdafc": {
|
||||
"T000001": {
|
||||
"level": "H1", "title": "My Novel", "layout": "TITLE", "synopsis": "text",
|
||||
"cCount": 72, "wCount": 15, "pCount": 2, "updated": 1611922868
|
||||
}
|
||||
}
|
||||
}
|
||||
theIndex._noteIndex = theIndex._novelIndex.copy()
|
||||
assert theIndex._checkNovelNoteIndex("novelIndex") is None
|
||||
assert theIndex._checkNovelNoteIndex("noteIndex") is None
|
||||
with pytest.raises(IndexError):
|
||||
theIndex._checkNovelNoteIndex("notAnIndex")
|
||||
|
||||
# Invalid Handle
|
||||
theIndex._novelIndex = {
|
||||
"H3b69b83cdafc": {
|
||||
"T000001": {
|
||||
"level": "H1", "title": "My Novel", "layout": "TITLE", "synopsis": "text",
|
||||
"cCount": 72, "wCount": 15, "pCount": 2, "updated": 1611922868
|
||||
}
|
||||
}
|
||||
}
|
||||
with pytest.raises(KeyError):
|
||||
theIndex._checkNovelNoteIndex("novelIndex")
|
||||
|
||||
# Invalid Title
|
||||
theIndex._novelIndex = {
|
||||
"53b69b83cdafc": {
|
||||
"INVALID": {
|
||||
"level": "H1", "title": "My Novel", "layout": "TITLE", "synopsis": "text",
|
||||
"cCount": 72, "wCount": 15, "pCount": 2, "updated": 1611922868
|
||||
}
|
||||
}
|
||||
}
|
||||
with pytest.raises(KeyError):
|
||||
theIndex._checkNovelNoteIndex("novelIndex")
|
||||
|
||||
# Wrong Length
|
||||
theIndex._novelIndex = {
|
||||
"53b69b83cdafc": {
|
||||
"T000001": {
|
||||
"level": "H1", "title": "My Novel", "layout": "TITLE", "synopsis": "text",
|
||||
"cCount": 72, "wCount": 15, "pCount": 2, "updated": 1611922868, "stuff": None
|
||||
}
|
||||
}
|
||||
}
|
||||
with pytest.raises(IndexError):
|
||||
theIndex._checkNovelNoteIndex("novelIndex")
|
||||
|
||||
# Missing Keys
|
||||
# ============
|
||||
|
||||
# Missing 'level'
|
||||
theIndex._novelIndex = {
|
||||
"53b69b83cdafc": {
|
||||
"T000001": {
|
||||
"stuff": "H1", "title": "My Novel", "layout": "TITLE", "synopsis": "text",
|
||||
"cCount": 72, "wCount": 15, "pCount": 2, "updated": 1611922868
|
||||
}
|
||||
}
|
||||
}
|
||||
with pytest.raises(KeyError):
|
||||
theIndex._checkNovelNoteIndex("novelIndex")
|
||||
|
||||
# Missing 'title'
|
||||
theIndex._novelIndex = {
|
||||
"53b69b83cdafc": {
|
||||
"T000001": {
|
||||
"level": "H1", "stuff": "My Novel", "layout": "TITLE", "synopsis": "text",
|
||||
"cCount": 72, "wCount": 15, "pCount": 2, "updated": 1611922868
|
||||
}
|
||||
}
|
||||
}
|
||||
with pytest.raises(KeyError):
|
||||
theIndex._checkNovelNoteIndex("novelIndex")
|
||||
|
||||
# Missing 'layout'
|
||||
theIndex._novelIndex = {
|
||||
"53b69b83cdafc": {
|
||||
"T000001": {
|
||||
"level": "H1", "title": "My Novel", "stuff": "TITLE", "synopsis": "text",
|
||||
"cCount": 72, "wCount": 15, "pCount": 2, "updated": 1611922868
|
||||
}
|
||||
}
|
||||
}
|
||||
with pytest.raises(KeyError):
|
||||
theIndex._checkNovelNoteIndex("novelIndex")
|
||||
|
||||
# Missing 'synopsis'
|
||||
theIndex._novelIndex = {
|
||||
"53b69b83cdafc": {
|
||||
"T000001": {
|
||||
"level": "H1", "title": "My Novel", "layout": "TITLE", "stuff": "text",
|
||||
"cCount": 72, "wCount": 15, "pCount": 2, "updated": 1611922868
|
||||
}
|
||||
}
|
||||
}
|
||||
with pytest.raises(KeyError):
|
||||
theIndex._checkNovelNoteIndex("novelIndex")
|
||||
|
||||
# Missing 'cCount'
|
||||
theIndex._novelIndex = {
|
||||
"53b69b83cdafc": {
|
||||
"T000001": {
|
||||
"level": "H1", "title": "My Novel", "layout": "TITLE", "synopsis": "text",
|
||||
"stuff": 72, "wCount": 15, "pCount": 2, "updated": 1611922868
|
||||
}
|
||||
}
|
||||
}
|
||||
with pytest.raises(KeyError):
|
||||
theIndex._checkNovelNoteIndex("novelIndex")
|
||||
|
||||
# Missing 'wCount'
|
||||
theIndex._novelIndex = {
|
||||
"53b69b83cdafc": {
|
||||
"T000001": {
|
||||
"level": "H1", "title": "My Novel", "layout": "TITLE", "synopsis": "text",
|
||||
"cCount": 72, "stuff": 15, "pCount": 2, "updated": 1611922868
|
||||
}
|
||||
}
|
||||
}
|
||||
with pytest.raises(KeyError):
|
||||
theIndex._checkNovelNoteIndex("novelIndex")
|
||||
|
||||
# Missing 'pCount'
|
||||
theIndex._novelIndex = {
|
||||
"53b69b83cdafc": {
|
||||
"T000001": {
|
||||
"level": "H1", "title": "My Novel", "layout": "TITLE", "synopsis": "text",
|
||||
"cCount": 72, "wCount": 15, "stuff": 2, "updated": 1611922868
|
||||
}
|
||||
}
|
||||
}
|
||||
with pytest.raises(KeyError):
|
||||
theIndex._checkNovelNoteIndex("novelIndex")
|
||||
|
||||
# Missing 'updated'
|
||||
theIndex._novelIndex = {
|
||||
"53b69b83cdafc": {
|
||||
"T000001": {
|
||||
"level": "H1", "title": "My Novel", "layout": "TITLE", "synopsis": "text",
|
||||
"cCount": 72, "wCount": 15, "pCount": 2, "stuff": 1611922868
|
||||
}
|
||||
}
|
||||
}
|
||||
with pytest.raises(KeyError):
|
||||
theIndex._checkNovelNoteIndex("novelIndex")
|
||||
|
||||
# Wrong Types
|
||||
# ===========
|
||||
|
||||
# Wrong Type for 'level'
|
||||
theIndex._novelIndex = {
|
||||
"53b69b83cdafc": {
|
||||
"T000001": {
|
||||
"level": "XX", "title": "My Novel", "layout": "TITLE", "synopsis": "text",
|
||||
"cCount": 72, "wCount": 15, "pCount": 2, "updated": 1611922868
|
||||
}
|
||||
}
|
||||
}
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkNovelNoteIndex("novelIndex")
|
||||
|
||||
# Wrong Type for 'title'
|
||||
theIndex._novelIndex = {
|
||||
"53b69b83cdafc": {
|
||||
"T000001": {
|
||||
"level": "H1", "title": 12345678, "layout": "TITLE", "synopsis": "text",
|
||||
"cCount": 72, "wCount": 15, "pCount": 2, "updated": 1611922868
|
||||
}
|
||||
}
|
||||
}
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkNovelNoteIndex("novelIndex")
|
||||
|
||||
# Wrong Type for 'layout'
|
||||
theIndex._novelIndex = {
|
||||
"53b69b83cdafc": {
|
||||
"T000001": {
|
||||
"level": "H1", "title": "My Novel", "layout": "INVALID", "synopsis": "text",
|
||||
"cCount": 72, "wCount": 15, "pCount": 2, "updated": 1611922868
|
||||
}
|
||||
}
|
||||
}
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkNovelNoteIndex("novelIndex")
|
||||
|
||||
# Wrong Type for 'synopsis'
|
||||
theIndex._novelIndex = {
|
||||
"53b69b83cdafc": {
|
||||
"T000001": {
|
||||
"level": "H1", "title": "My Novel", "layout": "TITLE", "synopsis": 123456,
|
||||
"cCount": 72, "wCount": 15, "pCount": 2, "updated": 1611922868
|
||||
}
|
||||
}
|
||||
}
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkNovelNoteIndex("novelIndex")
|
||||
|
||||
# Wrong Type for 'cCount'
|
||||
theIndex._novelIndex = {
|
||||
"53b69b83cdafc": {
|
||||
"T000001": {
|
||||
"level": "H1", "title": "My Novel", "layout": "TITLE", "synopsis": "text",
|
||||
"cCount": "72", "wCount": 15, "pCount": 2, "updated": 1611922868
|
||||
}
|
||||
}
|
||||
}
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkNovelNoteIndex("novelIndex")
|
||||
|
||||
# Wrong Type for 'wCount'
|
||||
theIndex._novelIndex = {
|
||||
"53b69b83cdafc": {
|
||||
"T000001": {
|
||||
"level": "H1", "title": "My Novel", "layout": "TITLE", "synopsis": "text",
|
||||
"cCount": 72, "wCount": "15", "pCount": 2, "updated": 1611922868
|
||||
}
|
||||
}
|
||||
}
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkNovelNoteIndex("novelIndex")
|
||||
|
||||
# Wrong Type for 'pCount'
|
||||
theIndex._novelIndex = {
|
||||
"53b69b83cdafc": {
|
||||
"T000001": {
|
||||
"level": "H1", "title": "My Novel", "layout": "TITLE", "synopsis": "text",
|
||||
"cCount": 72, "wCount": 15, "pCount": "2", "updated": 1611922868
|
||||
}
|
||||
}
|
||||
}
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkNovelNoteIndex("novelIndex")
|
||||
|
||||
# Wrong Type for 'updated'
|
||||
theIndex._novelIndex = {
|
||||
"53b69b83cdafc": {
|
||||
"T000001": {
|
||||
"level": "H1", "title": "My Novel", "layout": "TITLE", "synopsis": "text",
|
||||
"cCount": 72, "wCount": 15, "pCount": 2, "updated": "1611922868"
|
||||
}
|
||||
}
|
||||
}
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkNovelNoteIndex("novelIndex")
|
||||
|
||||
# END Test testCoreIndex_CheckNovelNoteIndex
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreIndex_CheckTextCounts(dummyGUI):
|
||||
"""Test the text counts checker.
|
||||
"""
|
||||
theProject = NWProject(dummyGUI)
|
||||
theIndex = NWIndex(theProject, dummyGUI)
|
||||
|
||||
# Valid Index
|
||||
theIndex._textCounts = {
|
||||
"53b69b83cdafc": [72, 15, 2],
|
||||
"974e400180a99": [210, 40, 2],
|
||||
}
|
||||
assert theIndex._checkTextCounts() is None
|
||||
|
||||
# Invalid Handle
|
||||
theIndex._textCounts = {
|
||||
"53b69b83cdafc": [72, 15, 2],
|
||||
"h74e400180a99": [210, 40, 2],
|
||||
}
|
||||
with pytest.raises(KeyError):
|
||||
theIndex._checkTextCounts()
|
||||
|
||||
# Wrong Length
|
||||
theIndex._textCounts = {
|
||||
"53b69b83cdafc": [72, 15, 2],
|
||||
"974e400180a99": [210, 40, 2, 8],
|
||||
}
|
||||
with pytest.raises(IndexError):
|
||||
theIndex._checkTextCounts()
|
||||
|
||||
# Type of Entry 0
|
||||
theIndex._textCounts = {
|
||||
"53b69b83cdafc": [72, 15, 2],
|
||||
"974e400180a99": ["210", 40, 2],
|
||||
}
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkTextCounts()
|
||||
|
||||
# Type of Entry 1
|
||||
theIndex._textCounts = {
|
||||
"53b69b83cdafc": [72, 15, 2],
|
||||
"974e400180a99": [210, "40", 2],
|
||||
}
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkTextCounts()
|
||||
|
||||
# Type of Entry 2
|
||||
theIndex._textCounts = {
|
||||
"53b69b83cdafc": [72, 15, 2],
|
||||
"974e400180a99": [210, 40, "2"],
|
||||
}
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkTextCounts()
|
||||
|
||||
# END Test testCoreIndex_CheckTextCounts
|
||||
|
||||
Reference in New Issue
Block a user