1from unittest.mock import MagicMock
2import os
3from io import StringIO
4from UM.Preferences import Preferences
5import pytest
6from UM.Resources import Resources
7
8Resources.addSearchPath(os.path.dirname(os.path.abspath(__file__)))
9
10
11test_Preference_data = [
12    {"key": "test/zomg", "default": 10},
13    {"key": "test/BLORP", "default": "True"},
14    {"key": "testing/BLORP", "default": "False"},
15    {"key": "testing/omgzomg", "default": dict()}
16]
17
18test_newValues_data = [None, 10, "omgzomg", -20, 12.1, 2j, {"test", "more_test"}, [10, 20, 30], "True", "true", dict()]
19
20
21# Preferences parses "True" to True and "False" to False
22def parseValue(value):
23    if value == "True":
24        return True
25    elif value == "False":
26        return False
27    else:
28        return value
29
30
31def test_readWrite():
32    preferences = Preferences()
33    path = Resources.getPath(Resources.Preferences, "preferences_test.cfg")
34    preferences.readFromFile(path)
35
36    # Check if it has been loaded correctly
37    assert preferences.getValue("general/foo") == "omgzomg"
38    assert preferences.getValue("general/derp") == True
39
40    # Write contents of the preference to a buffer
41    in_memory_storage = StringIO()
42    preferences.writeToFile(in_memory_storage)  # type: ignore
43
44    new_preferences = Preferences()
45    # For some reason, if write was used, the read doesn't work. If we do it like this, it does work.
46    new_preferences.readFromFile(StringIO(in_memory_storage.getvalue()))
47
48    assert preferences.getValue("general/foo") == new_preferences.getValue("general/foo")
49    assert preferences.getValue("test/more_test") == new_preferences.getValue("test/more_test")
50
51
52def test_deserialize():
53    preferences = Preferences()
54    path = Resources.getPath(Resources.Preferences, "preferences_test.cfg")
55
56    with open(path, "r", encoding="utf-8") as f:
57        preferences.deserialize(f.read())
58    assert preferences.getValue("general/foo") == "omgzomg"
59    assert preferences.getValue("general/derp") == True
60
61
62def test_malformattedKey():
63    preferences = Preferences()
64    with pytest.raises(Exception):
65        preferences.addPreference("DERP", "DERP")
66
67
68@pytest.mark.parametrize("preference", test_Preference_data)
69def test_addPreference(preference):
70    preferences = Preferences()
71    preferences.addPreference(preference["key"], preference["default"])
72    assert preferences.getValue(preference["key"]) == parseValue(preference["default"])
73
74    # Attempt to add the preference again, but with a different default.
75    preferences.addPreference(preference["key"], preference["key"])
76    assert preferences.getValue(preference["key"]) == parseValue(preference["key"])
77
78
79@pytest.mark.parametrize("preference", test_Preference_data)
80def test_removePreference(preference):
81    preferences = Preferences()
82    preferences.addPreference(preference["key"], preference["default"])
83    preferences.removePreference(preference["key"])
84    assert preferences.getValue(preference["key"]) is None
85
86
87@pytest.mark.parametrize("new_value", test_newValues_data)
88def test_setResetValue(new_value):
89    preferences = Preferences()
90    default_value = "omgzomg"
91    preferences.preferenceChanged.emit = MagicMock()
92    preferences.addPreference("test/test", default_value)
93    assert preferences.preferenceChanged.emit.call_count == 0
94    preferences.setValue("test/test", new_value)
95    assert preferences.getValue("test/test") == parseValue(new_value)
96
97    if new_value != default_value:
98        assert preferences.preferenceChanged.emit.call_count == 1
99
100    preferences.resetPreference("test/test")
101    if new_value != default_value:
102        assert preferences.preferenceChanged.emit.call_count == 2
103    else:
104        # The preference never changed. Neither the set or the reset should trigger an emit.
105        assert preferences.preferenceChanged.emit.call_count == 0
106
107    assert preferences.getValue("test/test") == default_value
108
109
110def test_nonExistingSetting():
111    preferences = Preferences()
112    # Test that attempting to modify a non existing setting in any way doesn't break things.
113    preferences.setDefault("nonExistingPreference", "whatever")
114    preferences.setValue("nonExistingPreference", "whatever")
115    preferences.removePreference("nonExistingPreference")