1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
# Copyright (c) 2013 Hesky Fisher
# See LICENSE.txt for details.
"""Tests for loading_manager.py."""
from collections import defaultdict
import os
import tempfile
import pytest
from plover.exception import DictionaryLoaderException
import plover.dictionary.loading_manager as loading_manager
class FakeDictionaryContents:
def __init__(self, contents, timestamp):
self.contents = contents
self.timestamp = timestamp
def __eq__(self, other):
if isinstance(other, FakeDictionaryContents):
return self.contents == other.contents
return self.contents == other
class FakeDictionaryInfo:
def __init__(self, name, contents):
self.name = name
self.contents = contents
self.tf = tempfile.NamedTemporaryFile()
def __repr__(self):
return "FakeDictionaryInfo(%r, %r)" % (self.name, self.contents)
class MockLoader:
def __init__(self, files):
self.files = files
self.load_counts = defaultdict(int)
def __call__(self, filename):
self.load_counts[filename] += 1
d = self.files[filename]
if isinstance(d.contents, Exception):
raise d.contents
timestamp = os.path.getmtime(filename)
return FakeDictionaryContents(d.contents, timestamp)
def test_loading(monkeypatch):
dictionaries = {}
for i in range(8):
c = chr(ord("a") + i)
contents = c * 5
if i >= 4:
contents = Exception(contents)
d = FakeDictionaryInfo(c, contents)
assert d.tf.name not in dictionaries
dictionaries[d.tf.name] = d
assert c not in dictionaries
dictionaries[c] = d
def df(name):
return dictionaries[name].tf.name
loader = MockLoader(dictionaries)
monkeypatch.setattr("plover.dictionary.loading_manager.load_dictionary", loader)
manager = loading_manager.DictionaryLoadingManager()
manager.start_loading(df("a")).get()
manager.start_loading(df("b")).get()
results = manager.load([df("c"), df("b")])
# Returns the right values in the right order.
assert results == ["ccccc", "bbbbb"]
# Dropped superfluous files.
assert sorted([df("b"), df("c")]) == sorted(manager.dictionaries.keys())
# Check dict like interface.
assert len(manager) == 2
assert df("a") not in manager
with pytest.raises(KeyError):
manager[df("a")]
assert df("b") in manager
assert df("c") in manager
assert results == [manager[df("c")], manager[df("b")]]
# Return a DictionaryLoaderException for load errors.
results = manager.load([df("c"), df("e"), df("b"), df("f")])
assert len(results) == 4
assert results[0] == "ccccc"
assert results[2] == "bbbbb"
assert isinstance(results[1], DictionaryLoaderException)
assert results[1].path == df("e")
assert isinstance(results[1].exception, Exception)
assert isinstance(results[3], DictionaryLoaderException)
assert results[3].path == df("f")
assert isinstance(results[3].exception, Exception)
# Only loaded the files once.
assert all(x == 1 for x in loader.load_counts.values())
# No reload if file timestamp is unchanged, or the dictionary
# timestamp is more recent. (use case: dictionary edited with
# Plover and saved back)
file_timestamp = results[0].timestamp
results[0].timestamp = file_timestamp + 1
dictionaries["c"].contents = "CCCCC"
results = manager.load([df("c")])
assert results == ["ccccc"]
assert loader.load_counts[df("c")] == 1
# Check outdated dictionaries are reloaded.
results[0].timestamp = file_timestamp - 1
results = manager.load([df("c")])
assert results == ["CCCCC"]
assert loader.load_counts[df("c")] == 2
# Check trimming of outdated dictionaries.
results[0].timestamp = file_timestamp - 1
manager.unload_outdated()
assert len(manager) == 0
assert df("c") not in manager
|