1from unittest.mock import MagicMock
2
3from UM.OutputDevice.OutputDevice import OutputDevice
4from UM.OutputDevice.OutputDeviceManager import OutputDeviceManager
5from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
6
7
8def test_addRemoveOutputDevice():
9    manager = OutputDeviceManager()
10
11    manager.outputDevicesChanged.emit = MagicMock()
12    manager.activeDeviceChanged.emit = MagicMock()
13
14    output_device = OutputDevice("test_device_one")
15    output_device.setPriority(2)
16    output_device_2 = OutputDevice("test_device_two")
17    output_device_2.setPriority(9001)
18
19    manager.addOutputDevice(output_device)
20    assert manager.outputDevicesChanged.emit.call_count == 1
21    assert manager.getOutputDevice("test_device_one") == output_device
22
23    # Our new device is also the one with the highest priority (as it's the only one). So it should be active.
24    assert manager.getActiveDevice() == output_device
25
26    manager.addOutputDevice(output_device)
27    assert manager.outputDevicesChanged.emit.call_count == 1
28
29    manager.addOutputDevice(output_device_2)
30    assert manager.outputDevicesChanged.emit.call_count == 2
31    # We added a new device with a higher priority, so that one should be the active one
32    assert manager.getActiveDevice() == output_device_2
33
34    assert set([output_device, output_device_2]) == set(manager.getOutputDevices())
35    assert set(["test_device_one", "test_device_two"]) == set(manager.getOutputDeviceIds())
36
37    # Try to manually change the active device a few times
38    manager.setActiveDevice("test_device_one")
39    assert manager.activeDeviceChanged.emit.call_count == 3
40    assert manager.getActiveDevice() == output_device
41    manager.setActiveDevice("test_device_two")
42    assert manager.activeDeviceChanged.emit.call_count == 4
43    assert manager.getActiveDevice() == output_device_2
44
45    # As usual, doing it twice shouldn't cause more updates
46    manager.setActiveDevice("test_device_two")
47    assert manager.activeDeviceChanged.emit.call_count == 4
48    manager.setActiveDevice("Whatever")  # Simply shouldn't cause issues.
49
50    # Time to remove the device again
51    assert manager.removeOutputDevice("test_device_two")
52    assert manager.getActiveDevice() == output_device
53    assert manager.outputDevicesChanged.emit.call_count == 3
54    # Trying to remove it again should return false
55    assert not manager.removeOutputDevice("test_device_two")
56    assert manager.outputDevicesChanged.emit.call_count == 3
57
58
59def test_addRemoveOutputDevicePlugin():
60    manager = OutputDeviceManager()
61    plugin_1 = OutputDevicePlugin()
62    plugin_1.setPluginId("plugin_one")
63
64    plugin_1.start = MagicMock()
65    plugin_1.stop = MagicMock()
66
67    manager.addOutputDevicePlugin(plugin_1)
68    assert manager.getOutputDevicePlugin("plugin_one") == plugin_1
69    # Outputdevice manager wasn't started, so the start of the plugin should not be called
70    assert plugin_1.start.call_count == 0
71
72    # So once we do, it should be called.
73    manager.start()
74    assert plugin_1.start.call_count == 1
75
76    # Adding it again shouldn't cause the start to be called again!
77    manager.addOutputDevicePlugin(plugin_1)
78    assert plugin_1.start.call_count == 1
79
80    manager.removeOutputDevicePlugin("plugin_one")
81    assert manager.getOutputDevicePlugin("plugin_one") is None
82    assert plugin_1.start.call_count == 1
83
84    # And removing it again shouldn't cause issues.
85    manager.removeOutputDevicePlugin("plugin_two")
86    assert plugin_1.start.call_count == 1
87
88    # As the default output device plugin is an interface, the start and stop will raise exceptions.
89    # but the outputdevice manager should be robust against that, so even in that case it shouldn't fail!
90    plugin_2 = OutputDevicePlugin()
91    plugin_2.setPluginId("plugin_two")
92    manager.addOutputDevicePlugin(plugin_2)
93    manager.removeOutputDevicePlugin("plugin_two")
94
95