[tests] Purge tests and start with a clean implementation of subprocess
Seems like subprocess and friends (Popen, communicate) are not so easy to mock cleanly. Therefore, start from scratch and carefully write test by test, until (at least) the old test coverage has been restored.
This commit is contained in:
parent
1c6122fc3f
commit
6dbe440cb5
23 changed files with 61 additions and 1240 deletions
|
@ -15,6 +15,8 @@ def execute(cmd, wait=True):
|
||||||
out, _ = proc.communicate()
|
out, _ = proc.communicate()
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
raise RuntimeError("{} exited with {}".format(cmd, proc.returncode))
|
raise RuntimeError("{} exited with {}".format(cmd, proc.returncode))
|
||||||
|
if type(out) == str:
|
||||||
|
return out
|
||||||
return out.decode("utf-8")
|
return out.decode("utf-8")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
27
tests/mocks.py
Normal file
27
tests/mocks.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# pylint: disable=C0103,C0111
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import shlex
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
class MockPopen(object):
|
||||||
|
def __init__(self, module):
|
||||||
|
self._patch = mock.patch("{}.subprocess.Popen".format(module))
|
||||||
|
self._popen = self._patch.start()
|
||||||
|
self.mock = mock.Mock()
|
||||||
|
# for a nicer, more uniform interface
|
||||||
|
self.mock.popen = self._popen
|
||||||
|
# for easier command execution checks
|
||||||
|
self.mock.popen.assert_call = self.assert_call
|
||||||
|
self._popen.return_value = self.mock
|
||||||
|
|
||||||
|
self.mock.communicate.return_value = [ "", None ]
|
||||||
|
self.mock.returncode = 0
|
||||||
|
|
||||||
|
def assert_call(self, cmd):
|
||||||
|
self.mock.popen.assert_called_with(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
self._patch.stop()
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
@ -1,68 +0,0 @@
|
||||||
# pylint: disable=C0103,C0111
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import json
|
|
||||||
import unittest
|
|
||||||
import mock
|
|
||||||
|
|
||||||
from contextlib import contextmanager
|
|
||||||
|
|
||||||
import bumblebee.input
|
|
||||||
from bumblebee.input import I3BarInput
|
|
||||||
from bumblebee.modules.battery import Module
|
|
||||||
from tests.util import MockEngine, MockConfig, assertPopen
|
|
||||||
|
|
||||||
class MockOpen(object):
|
|
||||||
def __init__(self):
|
|
||||||
self._value = ""
|
|
||||||
|
|
||||||
def returns(self, value):
|
|
||||||
self._value = value
|
|
||||||
|
|
||||||
def __enter__(self):
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __exit__(self, a, b, c):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def read(self):
|
|
||||||
return self._value
|
|
||||||
|
|
||||||
class TestBatteryModule(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.engine = MockEngine()
|
|
||||||
self.config = MockConfig()
|
|
||||||
self.module = Module(engine=self.engine, config={ "config": self.config })
|
|
||||||
for widget in self.module.widgets():
|
|
||||||
widget.link_module(self.module)
|
|
||||||
|
|
||||||
@mock.patch("sys.stdout")
|
|
||||||
def test_format(self, mock_output):
|
|
||||||
for widget in self.module.widgets():
|
|
||||||
self.assertEquals(len(widget.full_text()), len("100%"))
|
|
||||||
|
|
||||||
@mock.patch("os.path.exists")
|
|
||||||
@mock.patch("{}.open".format("__builtin__" if sys.version_info[0] < 3 else "builtins"))
|
|
||||||
@mock.patch("subprocess.Popen")
|
|
||||||
def test_critical(self, mock_output, mock_open, mock_exists):
|
|
||||||
mock_open.return_value = MockOpen()
|
|
||||||
mock_open.return_value.returns("19")
|
|
||||||
mock_exists.return_value = True
|
|
||||||
self.config.set("battery.critical", "20")
|
|
||||||
self.config.set("battery.warning", "25")
|
|
||||||
self.module.update(self.module.widgets())
|
|
||||||
self.assertTrue("critical" in self.module.widgets()[0].state())
|
|
||||||
|
|
||||||
@mock.patch("os.path.exists")
|
|
||||||
@mock.patch("{}.open".format("__builtin__" if sys.version_info[0] < 3 else "builtins"))
|
|
||||||
@mock.patch("subprocess.Popen")
|
|
||||||
def test_warning(self, mock_output, mock_open, mock_exists):
|
|
||||||
mock_open.return_value = MockOpen()
|
|
||||||
mock_exists.return_value = True
|
|
||||||
mock_open.return_value.returns("22")
|
|
||||||
self.config.set("battery.critical", "20")
|
|
||||||
self.config.set("battery.warning", "25")
|
|
||||||
self.module.update(self.module.widgets())
|
|
||||||
self.assertTrue("warning" in self.module.widgets()[0].state())
|
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
|
@ -1,56 +0,0 @@
|
||||||
# pylint: disable=C0103,C0111
|
|
||||||
|
|
||||||
import json
|
|
||||||
import unittest
|
|
||||||
import mock
|
|
||||||
|
|
||||||
import bumblebee.input
|
|
||||||
from bumblebee.input import I3BarInput
|
|
||||||
from bumblebee.modules.brightness import Module
|
|
||||||
from tests.util import MockEngine, MockConfig, assertPopen, assertMouseEvent
|
|
||||||
|
|
||||||
class TestBrightnessModule(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.engine = MockEngine()
|
|
||||||
self.engine.input = I3BarInput()
|
|
||||||
self.engine.input.need_event = True
|
|
||||||
self.config = MockConfig()
|
|
||||||
self.module = Module(engine=self.engine, config={ "config": self.config })
|
|
||||||
for widget in self.module.widgets():
|
|
||||||
widget.link_module(self.module)
|
|
||||||
|
|
||||||
@mock.patch("sys.stdout")
|
|
||||||
def test_format(self, mock_output):
|
|
||||||
for widget in self.module.widgets():
|
|
||||||
self.assertEquals(len(widget.full_text()), len("100%"))
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("subprocess.Popen")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_wheel_up(self, mock_input, mock_output, mock_select):
|
|
||||||
assertMouseEvent(mock_input, mock_output, mock_select, self.engine,
|
|
||||||
self.module, bumblebee.input.WHEEL_UP,
|
|
||||||
"xbacklight +2%"
|
|
||||||
)
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("subprocess.Popen")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_wheel_down(self, mock_input, mock_output, mock_select):
|
|
||||||
assertMouseEvent(mock_input, mock_output, mock_select, self.engine,
|
|
||||||
self.module, bumblebee.input.WHEEL_DOWN,
|
|
||||||
"xbacklight -2%"
|
|
||||||
)
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("subprocess.Popen")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_custom_step(self, mock_input, mock_output, mock_select):
|
|
||||||
self.config.set("brightness.step", "10")
|
|
||||||
module = Module(engine=self.engine, config={ "config": self.config })
|
|
||||||
assertMouseEvent(mock_input, mock_output, mock_select, self.engine,
|
|
||||||
module, bumblebee.input.WHEEL_DOWN,
|
|
||||||
"xbacklight -10%"
|
|
||||||
)
|
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
|
@ -1,21 +0,0 @@
|
||||||
# pylint: disable=C0103,C0111
|
|
||||||
|
|
||||||
import json
|
|
||||||
import unittest
|
|
||||||
import mock
|
|
||||||
|
|
||||||
import bumblebee.input
|
|
||||||
from bumblebee.input import I3BarInput
|
|
||||||
from bumblebee.modules.caffeine import Module
|
|
||||||
from tests.util import MockEngine, MockConfig, assertPopen
|
|
||||||
|
|
||||||
class TestCaffeineModule(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.engine = MockEngine()
|
|
||||||
self.engine.input = I3BarInput()
|
|
||||||
self.engine.input.need_event = True
|
|
||||||
self.engine.input.need_valid_event = True
|
|
||||||
self.config = MockConfig()
|
|
||||||
self.module = Module(engine=self.engine, config={ "config": self.config })
|
|
||||||
for widget in self.module.widgets():
|
|
||||||
widget.link_module(self.module)
|
|
|
@ -1,58 +0,0 @@
|
||||||
# pylint: disable=C0103,C0111
|
|
||||||
|
|
||||||
import json
|
|
||||||
import unittest
|
|
||||||
import mock
|
|
||||||
|
|
||||||
import bumblebee.input
|
|
||||||
from bumblebee.input import I3BarInput
|
|
||||||
from bumblebee.modules.cmus import Module
|
|
||||||
from tests.util import MockEngine, MockConfig, assertPopen, MockEpoll
|
|
||||||
|
|
||||||
class TestCmusModule(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.engine = MockEngine()
|
|
||||||
self.engine.input = I3BarInput()
|
|
||||||
self.engine.input.need_event = True
|
|
||||||
self.module = Module(engine=self.engine, config={"config": MockConfig()})
|
|
||||||
|
|
||||||
@mock.patch("subprocess.Popen")
|
|
||||||
def test_read_song(self, mock_output):
|
|
||||||
rv = mock.Mock()
|
|
||||||
rv.configure_mock(**{
|
|
||||||
"communicate.return_value": ("out", None)
|
|
||||||
})
|
|
||||||
mock_output.return_value = rv
|
|
||||||
self.module.update(self.module.widgets())
|
|
||||||
assertPopen(mock_output, "cmus-remote -Q")
|
|
||||||
|
|
||||||
def test_widgets(self):
|
|
||||||
self.assertTrue(len(self.module.widgets()), 5)
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("subprocess.Popen")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_interaction(self, mock_input, mock_output, mock_select):
|
|
||||||
events = [
|
|
||||||
{"widget": "cmus.shuffle", "action": "cmus-remote -S"},
|
|
||||||
{"widget": "cmus.repeat", "action": "cmus-remote -R"},
|
|
||||||
{"widget": "cmus.next", "action": "cmus-remote -n"},
|
|
||||||
{"widget": "cmus.prev", "action": "cmus-remote -r"},
|
|
||||||
{"widget": "cmus.main", "action": "cmus-remote -u"},
|
|
||||||
]
|
|
||||||
|
|
||||||
mock_input.fileno.return_value = 1
|
|
||||||
mock_select.return_value = MockEpoll()
|
|
||||||
|
|
||||||
for event in events:
|
|
||||||
mock_input.readline.return_value = json.dumps({
|
|
||||||
"name": self.module.id,
|
|
||||||
"button": bumblebee.input.LEFT_MOUSE,
|
|
||||||
"instance": self.module.widget(event["widget"]).id
|
|
||||||
})
|
|
||||||
self.engine.input.start()
|
|
||||||
self.engine.input.stop()
|
|
||||||
mock_input.readline.assert_any_call()
|
|
||||||
assertPopen(mock_output, event["action"])
|
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
|
@ -1,48 +0,0 @@
|
||||||
# pylint: disable=C0103,C0111
|
|
||||||
|
|
||||||
import json
|
|
||||||
import unittest
|
|
||||||
import mock
|
|
||||||
|
|
||||||
import bumblebee.input
|
|
||||||
from bumblebee.input import I3BarInput
|
|
||||||
from bumblebee.modules.cpu import Module
|
|
||||||
from tests.util import MockEngine, MockConfig, assertPopen, assertMouseEvent, assertStateContains
|
|
||||||
|
|
||||||
class TestCPUModule(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.engine = MockEngine()
|
|
||||||
self.engine.input = I3BarInput()
|
|
||||||
self.engine.input.need_event = True
|
|
||||||
self.config = MockConfig()
|
|
||||||
self.module = Module(engine=self.engine, config={ "config": self.config })
|
|
||||||
|
|
||||||
@mock.patch("sys.stdout")
|
|
||||||
def test_format(self, mock_output):
|
|
||||||
for widget in self.module.widgets():
|
|
||||||
self.assertEquals(len(widget.full_text()), len("100.00%"))
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("subprocess.Popen")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_leftclick(self, mock_input, mock_output, mock_select):
|
|
||||||
assertMouseEvent(mock_input, mock_output, mock_select, self.engine,
|
|
||||||
self.module, bumblebee.input.LEFT_MOUSE,
|
|
||||||
"gnome-system-monitor"
|
|
||||||
)
|
|
||||||
|
|
||||||
@mock.patch("psutil.cpu_percent")
|
|
||||||
def test_warning(self, mock_psutil):
|
|
||||||
self.config.set("cpu.critical", "20")
|
|
||||||
self.config.set("cpu.warning", "18")
|
|
||||||
mock_psutil.return_value = 19.0
|
|
||||||
assertStateContains(self, self.module, "warning")
|
|
||||||
|
|
||||||
@mock.patch("psutil.cpu_percent")
|
|
||||||
def test_critical(self, mock_psutil):
|
|
||||||
self.config.set("cpu.critical", "20")
|
|
||||||
self.config.set("cpu.warning", "19")
|
|
||||||
mock_psutil.return_value = 21.0
|
|
||||||
assertStateContains(self, self.module, "critical")
|
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
|
@ -1,56 +0,0 @@
|
||||||
# pylint: disable=C0103,C0111
|
|
||||||
|
|
||||||
import json
|
|
||||||
import unittest
|
|
||||||
import mock
|
|
||||||
|
|
||||||
import bumblebee.input
|
|
||||||
from bumblebee.input import I3BarInput
|
|
||||||
from bumblebee.modules.disk import Module
|
|
||||||
from tests.util import MockEngine, MockConfig, assertPopen, assertStateContains, MockEpoll
|
|
||||||
|
|
||||||
class MockVFS(object):
|
|
||||||
def __init__(self, perc):
|
|
||||||
self.f_blocks = 1024*1024
|
|
||||||
self.f_frsize = 1
|
|
||||||
self.f_bavail = self.f_blocks - self.f_blocks*(perc/100.0)
|
|
||||||
|
|
||||||
class TestDiskModule(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.engine = MockEngine()
|
|
||||||
self.engine.input = I3BarInput()
|
|
||||||
self.engine.input.need_event = True
|
|
||||||
self.config = MockConfig()
|
|
||||||
self.config.set("disk.path", "somepath")
|
|
||||||
self.module = Module(engine=self.engine, config={"config": self.config})
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("subprocess.Popen")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_leftclick(self, mock_input, mock_output, mock_select):
|
|
||||||
mock_input.readline.return_value = json.dumps({
|
|
||||||
"name": self.module.id,
|
|
||||||
"button": bumblebee.input.LEFT_MOUSE,
|
|
||||||
"instance": None
|
|
||||||
})
|
|
||||||
mock_select.return_value = MockEpoll()
|
|
||||||
self.engine.input.start()
|
|
||||||
self.engine.input.stop()
|
|
||||||
mock_input.readline.assert_any_call()
|
|
||||||
assertPopen(mock_output, "nautilus {}".format(self.module.parameter("path")))
|
|
||||||
|
|
||||||
@mock.patch("os.statvfs")
|
|
||||||
def test_warning(self, mock_stat):
|
|
||||||
self.config.set("disk.critical", "80")
|
|
||||||
self.config.set("disk.warning", "70")
|
|
||||||
mock_stat.return_value = MockVFS(75.0)
|
|
||||||
assertStateContains(self, self.module, "warning")
|
|
||||||
|
|
||||||
@mock.patch("os.statvfs")
|
|
||||||
def test_critical(self, mock_stat):
|
|
||||||
self.config.set("disk.critical", "80")
|
|
||||||
self.config.set("disk.warning", "70")
|
|
||||||
mock_stat.return_value = MockVFS(85.0)
|
|
||||||
assertStateContains(self, self.module, "critical")
|
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
|
@ -1,47 +0,0 @@
|
||||||
# pylint: disable=C0103,C0111
|
|
||||||
|
|
||||||
import json
|
|
||||||
import unittest
|
|
||||||
import mock
|
|
||||||
|
|
||||||
import bumblebee.input
|
|
||||||
from bumblebee.input import I3BarInput
|
|
||||||
from bumblebee.modules.load import Module
|
|
||||||
from tests.util import MockEngine, MockConfig, assertStateContains, assertMouseEvent
|
|
||||||
|
|
||||||
class TestLoadModule(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.engine = MockEngine()
|
|
||||||
self.engine.input = I3BarInput()
|
|
||||||
self.engine.input.need_event = True
|
|
||||||
self.config = MockConfig()
|
|
||||||
self.module = Module(engine=self.engine, config={ "config": self.config })
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("subprocess.Popen")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_leftclick(self, mock_input, mock_output, mock_select):
|
|
||||||
assertMouseEvent(mock_input, mock_output, mock_select, self.engine,
|
|
||||||
self.module, bumblebee.input.LEFT_MOUSE,
|
|
||||||
"gnome-system-monitor"
|
|
||||||
)
|
|
||||||
|
|
||||||
@mock.patch("multiprocessing.cpu_count")
|
|
||||||
@mock.patch("os.getloadavg")
|
|
||||||
def test_warning(self, mock_loadavg, mock_cpucount):
|
|
||||||
self.config.set("load.critical", "1")
|
|
||||||
self.config.set("load.warning", "0.8")
|
|
||||||
mock_cpucount.return_value = 1
|
|
||||||
mock_loadavg.return_value = [ 0.9, 0, 0 ]
|
|
||||||
assertStateContains(self, self.module, "warning")
|
|
||||||
|
|
||||||
@mock.patch("multiprocessing.cpu_count")
|
|
||||||
@mock.patch("os.getloadavg")
|
|
||||||
def test_critical(self, mock_loadavg, mock_cpucount):
|
|
||||||
self.config.set("load.critical", "1")
|
|
||||||
self.config.set("load.warning", "0.8")
|
|
||||||
mock_cpucount.return_value = 1
|
|
||||||
mock_loadavg.return_value = [ 1.1, 0, 0 ]
|
|
||||||
assertStateContains(self, self.module, "critical")
|
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
|
@ -1,47 +0,0 @@
|
||||||
# pylint: disable=C0103,C0111
|
|
||||||
|
|
||||||
import json
|
|
||||||
import unittest
|
|
||||||
import mock
|
|
||||||
|
|
||||||
import bumblebee.input
|
|
||||||
from bumblebee.input import I3BarInput
|
|
||||||
from bumblebee.modules.memory import Module
|
|
||||||
from tests.util import MockEngine, MockConfig, assertPopen, assertMouseEvent, assertStateContains
|
|
||||||
|
|
||||||
class VirtualMemory(object):
|
|
||||||
def __init__(self, percent):
|
|
||||||
self.percent = percent
|
|
||||||
|
|
||||||
class TestMemoryModule(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.engine = MockEngine()
|
|
||||||
self.engine.input = I3BarInput()
|
|
||||||
self.engine.input.need_event = True
|
|
||||||
self.config = MockConfig()
|
|
||||||
self.module = Module(engine=self.engine, config={ "config": self.config })
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("subprocess.Popen")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_leftclick(self, mock_input, mock_output, mock_select):
|
|
||||||
assertMouseEvent(mock_input, mock_output, mock_select, self.engine,
|
|
||||||
self.module, bumblebee.input.LEFT_MOUSE,
|
|
||||||
"gnome-system-monitor"
|
|
||||||
)
|
|
||||||
|
|
||||||
@mock.patch("psutil.virtual_memory")
|
|
||||||
def test_warning(self, mock_vmem):
|
|
||||||
self.config.set("memory.critical", "80")
|
|
||||||
self.config.set("memory.warning", "70")
|
|
||||||
mock_vmem.return_value = VirtualMemory(75)
|
|
||||||
assertStateContains(self, self.module, "warning")
|
|
||||||
|
|
||||||
@mock.patch("psutil.virtual_memory")
|
|
||||||
def test_critical(self, mock_vmem):
|
|
||||||
self.config.set("memory.critical", "80")
|
|
||||||
self.config.set("memory.warning", "70")
|
|
||||||
mock_vmem.return_value = VirtualMemory(85)
|
|
||||||
assertStateContains(self, self.module, "critical")
|
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
|
@ -1,57 +0,0 @@
|
||||||
# pylint: disable=C0103,C0111
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
import importlib
|
|
||||||
import mock
|
|
||||||
|
|
||||||
from bumblebee.engine import all_modules
|
|
||||||
from bumblebee.config import Config
|
|
||||||
from tests.util import assertWidgetAttributes, MockEngine
|
|
||||||
|
|
||||||
class MockCommunicate(object):
|
|
||||||
def __init__(self):
|
|
||||||
self.returncode = 0
|
|
||||||
|
|
||||||
def communicate(self):
|
|
||||||
return (str.encode("1"), "error")
|
|
||||||
|
|
||||||
class TestGenericModules(unittest.TestCase):
|
|
||||||
@mock.patch("subprocess.Popen")
|
|
||||||
def setUp(self, mock_output):
|
|
||||||
mock_output.return_value = MockCommunicate()
|
|
||||||
engine = MockEngine()
|
|
||||||
config = Config()
|
|
||||||
self.objects = {}
|
|
||||||
for mod in all_modules():
|
|
||||||
cls = importlib.import_module("bumblebee.modules.{}".format(mod["name"]))
|
|
||||||
self.objects[mod["name"]] = getattr(cls, "Module")(engine, {"config": config})
|
|
||||||
for widget in self.objects[mod["name"]].widgets():
|
|
||||||
self.assertEquals(widget.get("variable", None), None)
|
|
||||||
|
|
||||||
@mock.patch("subprocess.Popen")
|
|
||||||
def test_widgets(self, mock_output):
|
|
||||||
mock_output.return_value = MockCommunicate()
|
|
||||||
for mod in self.objects:
|
|
||||||
widgets = self.objects[mod].widgets()
|
|
||||||
for widget in widgets:
|
|
||||||
widget.link_module(self.objects[mod])
|
|
||||||
self.assertEquals(widget.module, mod)
|
|
||||||
assertWidgetAttributes(self, widget)
|
|
||||||
widget.set("variable", "value")
|
|
||||||
self.assertEquals(widget.get("variable", None), "value")
|
|
||||||
self.assertTrue(isinstance(widget.full_text(), str) or isinstance(widget.full_text(), unicode))
|
|
||||||
|
|
||||||
@mock.patch("subprocess.Popen")
|
|
||||||
def test_update(self, mock_output):
|
|
||||||
mock_output.return_value = MockCommunicate()
|
|
||||||
rv = mock.Mock()
|
|
||||||
rv.configure_mock(**{
|
|
||||||
"communicate.return_value": ("out", None)
|
|
||||||
})
|
|
||||||
for mod in self.objects:
|
|
||||||
widgets = self.objects[mod].widgets()
|
|
||||||
self.objects[mod].update(widgets)
|
|
||||||
self.test_widgets()
|
|
||||||
self.assertEquals(widgets, self.objects[mod].widgets())
|
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
|
@ -1,56 +0,0 @@
|
||||||
# pylint: disable=C0103,C0111
|
|
||||||
|
|
||||||
import json
|
|
||||||
import unittest
|
|
||||||
import mock
|
|
||||||
|
|
||||||
import bumblebee.input
|
|
||||||
from bumblebee.input import I3BarInput
|
|
||||||
from bumblebee.modules.pulseaudio import Module
|
|
||||||
from tests.util import MockEngine, MockConfig, assertPopen, assertMouseEvent, assertStateContains
|
|
||||||
|
|
||||||
class TestPulseAudioModule(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.engine = MockEngine()
|
|
||||||
self.engine.input = I3BarInput()
|
|
||||||
self.engine.input.need_event = True
|
|
||||||
self.config = MockConfig()
|
|
||||||
self.module = Module(engine=self.engine, config={ "config": self.config })
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("subprocess.Popen")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_leftclick(self, mock_input, mock_output, mock_select):
|
|
||||||
assertMouseEvent(mock_input, mock_output, mock_select, self.engine,
|
|
||||||
self.module, bumblebee.input.LEFT_MOUSE,
|
|
||||||
"pactl set-source-mute @DEFAULT_SOURCE@ toggle"
|
|
||||||
)
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("subprocess.Popen")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_rightclick(self, mock_input, mock_output, mock_select):
|
|
||||||
assertMouseEvent(mock_input, mock_output, mock_select, self.engine,
|
|
||||||
self.module, bumblebee.input.RIGHT_MOUSE,
|
|
||||||
"pavucontrol"
|
|
||||||
)
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("subprocess.Popen")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_wheelup(self, mock_input, mock_output, mock_select):
|
|
||||||
assertMouseEvent(mock_input, mock_output, mock_select, self.engine,
|
|
||||||
self.module, bumblebee.input.WHEEL_UP,
|
|
||||||
"pactl set-source-volume @DEFAULT_SOURCE@ +2%"
|
|
||||||
)
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("subprocess.Popen")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_wheeldown(self, mock_input, mock_output, mock_select):
|
|
||||||
assertMouseEvent(mock_input, mock_output, mock_select, self.engine,
|
|
||||||
self.module, bumblebee.input.WHEEL_DOWN,
|
|
||||||
"pactl set-source-volume @DEFAULT_SOURCE@ -2%"
|
|
||||||
)
|
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
|
@ -1,52 +0,0 @@
|
||||||
# pylint: disable=C0103,C0111
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
import mock
|
|
||||||
try:
|
|
||||||
from StringIO import StringIO
|
|
||||||
except ImportError:
|
|
||||||
from io import StringIO
|
|
||||||
|
|
||||||
from bumblebee.config import Config
|
|
||||||
from bumblebee.theme import themes
|
|
||||||
from bumblebee.engine import all_modules
|
|
||||||
|
|
||||||
class TestConfig(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.defaultConfig = Config()
|
|
||||||
self.someSimpleModules = ["foo", "bar", "baz"]
|
|
||||||
self.someAliasModules = ["foo:a", "bar:b", "baz:c"]
|
|
||||||
|
|
||||||
def test_no_modules_by_default(self):
|
|
||||||
self.assertEquals(self.defaultConfig.modules(), [])
|
|
||||||
|
|
||||||
def test_simple_modules(self):
|
|
||||||
cfg = Config(["-m"] + self.someSimpleModules)
|
|
||||||
self.assertEquals(cfg.modules(), [{
|
|
||||||
"name": x, "module": x
|
|
||||||
} for x in self.someSimpleModules])
|
|
||||||
|
|
||||||
def test_alias_modules(self):
|
|
||||||
cfg = Config(["-m"] + self.someAliasModules)
|
|
||||||
self.assertEquals(cfg.modules(), [{
|
|
||||||
"module": x.split(":")[0],
|
|
||||||
"name": x.split(":")[1],
|
|
||||||
} for x in self.someAliasModules])
|
|
||||||
|
|
||||||
@mock.patch("sys.stdout", new_callable=StringIO)
|
|
||||||
@mock.patch("sys.exit")
|
|
||||||
def test_list_themes(self, exit, stdout):
|
|
||||||
cfg = Config(["-l", "themes"])
|
|
||||||
result = stdout.getvalue()
|
|
||||||
for theme in themes():
|
|
||||||
self.assertTrue(theme in result)
|
|
||||||
|
|
||||||
@mock.patch("sys.stdout", new_callable=StringIO)
|
|
||||||
@mock.patch("sys.exit")
|
|
||||||
def test_list_modules(self, exit, stdout):
|
|
||||||
cfg = Config(["-l", "modules"])
|
|
||||||
result = stdout.getvalue()
|
|
||||||
for module in all_modules():
|
|
||||||
self.assertTrue(module["name"] in result)
|
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
|
@ -1,83 +0,0 @@
|
||||||
# pylint: disable=C0103,C0111,W0703,W0212
|
|
||||||
|
|
||||||
import shlex
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
from bumblebee.error import ModuleLoadError
|
|
||||||
from bumblebee.engine import Engine
|
|
||||||
from bumblebee.config import Config
|
|
||||||
import bumblebee.input
|
|
||||||
|
|
||||||
from tests.util import MockOutput, MockInput
|
|
||||||
|
|
||||||
class TestEngine(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.engine = Engine(config=Config(), output=MockOutput(), inp=MockInput())
|
|
||||||
self.singleWidgetModule = [{"module": "test", "name": "a"}]
|
|
||||||
self.testModule = "test"
|
|
||||||
self.invalidModule = "no-such-module"
|
|
||||||
self.testModuleSpec = "bumblebee.modules.{}".format(self.testModule)
|
|
||||||
self.testModules = [
|
|
||||||
{"module": "test", "name": "a"},
|
|
||||||
{"module": "test", "name": "b"},
|
|
||||||
]
|
|
||||||
|
|
||||||
def test_stop(self):
|
|
||||||
self.assertTrue(self.engine.running())
|
|
||||||
self.engine.stop()
|
|
||||||
self.assertFalse(self.engine.running())
|
|
||||||
|
|
||||||
def test_load_module(self):
|
|
||||||
module = self.engine._load_module(self.testModule)
|
|
||||||
self.assertEquals(module.__module__, self.testModuleSpec)
|
|
||||||
|
|
||||||
def test_load_invalid_module(self):
|
|
||||||
with self.assertRaises(ModuleLoadError):
|
|
||||||
self.engine._load_module(self.invalidModule)
|
|
||||||
|
|
||||||
def test_load_none(self):
|
|
||||||
with self.assertRaises(ModuleLoadError):
|
|
||||||
self.engine._load_module(None)
|
|
||||||
|
|
||||||
def test_load_modules(self):
|
|
||||||
modules = self.engine.load_modules(self.testModules)
|
|
||||||
self.assertEquals(len(modules), len(self.testModules))
|
|
||||||
self.assertEquals(
|
|
||||||
[module.__module__ for module in modules],
|
|
||||||
[self.testModuleSpec for module in modules]
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_run(self):
|
|
||||||
self.engine.load_modules(self.singleWidgetModule)
|
|
||||||
try:
|
|
||||||
self.engine.run()
|
|
||||||
except Exception as e:
|
|
||||||
self.fail(e)
|
|
||||||
|
|
||||||
def test_custom_cmd(self):
|
|
||||||
testmodules = [
|
|
||||||
{ "name": "test", "button": "test.left-click", "action": "echo" },
|
|
||||||
{ "name": "test:alias", "button": "alias.right-click", "action": "echo2" },
|
|
||||||
]
|
|
||||||
cmd = "-m"
|
|
||||||
for test in testmodules:
|
|
||||||
cmd += " " + test["name"]
|
|
||||||
cmd += " -p"
|
|
||||||
for test in testmodules:
|
|
||||||
cmd += " " + test["button"] + "=" + test["action"]
|
|
||||||
cfg = Config(shlex.split(cmd))
|
|
||||||
inp = MockInput()
|
|
||||||
engine = Engine(config=cfg, output=MockOutput(), inp=inp)
|
|
||||||
|
|
||||||
i = 0
|
|
||||||
for module in engine.modules():
|
|
||||||
callback = inp.get_callback(module.id)
|
|
||||||
self.assertTrue(callback is not None)
|
|
||||||
self.assertEquals(callback["command"], testmodules[i]["action"])
|
|
||||||
if "left" in testmodules[i]["button"]:
|
|
||||||
self.assertTrue(callback["button"], bumblebee.input.LEFT_MOUSE)
|
|
||||||
if "right" in testmodules[i]["button"]:
|
|
||||||
self.assertTrue(callback["button"], bumblebee.input.RIGHT_MOUSE)
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
|
@ -1,129 +0,0 @@
|
||||||
# pylint: disable=C0103,C0111
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
import json
|
|
||||||
import subprocess
|
|
||||||
import mock
|
|
||||||
|
|
||||||
import bumblebee.input
|
|
||||||
from bumblebee.input import I3BarInput
|
|
||||||
from tests.util import MockWidget, MockModule, assertPopen, assertMouseEvent, MockEpoll
|
|
||||||
|
|
||||||
class TestI3BarInput(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.input = I3BarInput()
|
|
||||||
self.input.need_event = True
|
|
||||||
self.anyModule = MockModule()
|
|
||||||
self.anyWidget = MockWidget("test")
|
|
||||||
self.anyModule.id = "test-module"
|
|
||||||
self._called = 0
|
|
||||||
|
|
||||||
def callback(self, event):
|
|
||||||
self._called += 1
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_basic_read_event(self, mock_input, mock_select):
|
|
||||||
mock_input.readline.return_value = "somedata"
|
|
||||||
mock_input.fileno.return_value = 1
|
|
||||||
mock_select.return_value = MockEpoll()
|
|
||||||
self.input.start()
|
|
||||||
self.input.stop()
|
|
||||||
mock_input.readline.assert_any_call()
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_ignore_invalid_data(self, mock_input, mock_select):
|
|
||||||
mock_select.return_value = MockEpoll()
|
|
||||||
mock_input.readline.return_value = "garbage"
|
|
||||||
self.input.start()
|
|
||||||
self.assertEquals(self.input.alive(), True)
|
|
||||||
self.assertEquals(self.input.stop(), True)
|
|
||||||
mock_input.readline.assert_any_call()
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_ignore_invalid_event(self, mock_input, mock_select):
|
|
||||||
mock_select.return_value = MockEpoll()
|
|
||||||
mock_input.readline.return_value = json.dumps({
|
|
||||||
"name": None,
|
|
||||||
"instance": None,
|
|
||||||
"button": 1,
|
|
||||||
})
|
|
||||||
self.input.start()
|
|
||||||
self.assertEquals(self.input.alive(), True)
|
|
||||||
self.assertEquals(self.input.stop(), True)
|
|
||||||
mock_input.readline.assert_any_call()
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_ignore_partial_event(self, mock_input, mock_select):
|
|
||||||
mock_select.return_value = MockEpoll()
|
|
||||||
self.input.register_callback(None, button=1, cmd=self.callback)
|
|
||||||
mock_input.readline.return_value = json.dumps({
|
|
||||||
"button": 1,
|
|
||||||
})
|
|
||||||
self.input.start()
|
|
||||||
self.assertEquals(self.input.alive(), True)
|
|
||||||
self.assertEquals(self.input.stop(), True)
|
|
||||||
mock_input.readline.assert_any_call()
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_global_callback(self, mock_input, mock_select):
|
|
||||||
self.input.register_callback(None, button=1, cmd=self.callback)
|
|
||||||
assertMouseEvent(mock_input, None, mock_select, self, None,
|
|
||||||
bumblebee.input.LEFT_MOUSE, None, "someinstance")
|
|
||||||
self.assertTrue(self._called > 0)
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_remove_global_callback(self, mock_input, mock_select):
|
|
||||||
self.input.register_callback(None, button=1, cmd=self.callback)
|
|
||||||
self.input.deregister_callbacks(None)
|
|
||||||
assertMouseEvent(mock_input, None, mock_select, self, None,
|
|
||||||
bumblebee.input.LEFT_MOUSE, None, "someinstance")
|
|
||||||
self.assertTrue(self._called == 0)
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_global_callback_button_missmatch(self, mock_input, mock_select):
|
|
||||||
self.input.register_callback(self.anyModule, button=1, cmd=self.callback)
|
|
||||||
assertMouseEvent(mock_input, None, mock_select, self, None,
|
|
||||||
bumblebee.input.RIGHT_MOUSE, None, "someinstance")
|
|
||||||
self.assertTrue(self._called == 0)
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_module_callback(self, mock_input, mock_select):
|
|
||||||
self.input.register_callback(self.anyModule, button=1, cmd=self.callback)
|
|
||||||
assertMouseEvent(mock_input, None, mock_select, self, self.anyModule,
|
|
||||||
bumblebee.input.LEFT_MOUSE, None)
|
|
||||||
self.assertTrue(self._called > 0)
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_remove_module_callback(self, mock_input, mock_select):
|
|
||||||
self.input.register_callback(self.anyModule, button=1, cmd=self.callback)
|
|
||||||
self.input.deregister_callbacks(self.anyModule)
|
|
||||||
assertMouseEvent(mock_input, None, mock_select, self, None,
|
|
||||||
bumblebee.input.LEFT_MOUSE, None, self.anyWidget.id)
|
|
||||||
self.assertTrue(self._called == 0)
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_widget_callback(self, mock_input, mock_select):
|
|
||||||
self.input.register_callback(self.anyWidget, button=1, cmd=self.callback)
|
|
||||||
assertMouseEvent(mock_input, None, mock_select, self, None,
|
|
||||||
bumblebee.input.LEFT_MOUSE, None, self.anyWidget.id)
|
|
||||||
self.assertTrue(self._called > 0)
|
|
||||||
|
|
||||||
@mock.patch("select.epoll")
|
|
||||||
@mock.patch("subprocess.Popen")
|
|
||||||
@mock.patch("sys.stdin")
|
|
||||||
def test_widget_cmd_callback(self, mock_input, mock_output, mock_select):
|
|
||||||
self.input.register_callback(self.anyWidget, button=1, cmd="echo")
|
|
||||||
assertMouseEvent(mock_input, mock_output, mock_select, self, None,
|
|
||||||
bumblebee.input.LEFT_MOUSE, "echo", self.anyWidget.id)
|
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
|
@ -1,104 +0,0 @@
|
||||||
# pylint: disable=C0103,C0111
|
|
||||||
|
|
||||||
import json
|
|
||||||
import unittest
|
|
||||||
import mock
|
|
||||||
try:
|
|
||||||
from StringIO import StringIO
|
|
||||||
except ImportError:
|
|
||||||
from io import StringIO
|
|
||||||
|
|
||||||
from bumblebee.output import I3BarOutput
|
|
||||||
from tests.util import MockWidget, MockTheme, MockModule
|
|
||||||
|
|
||||||
class TestI3BarOutput(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.theme = MockTheme()
|
|
||||||
self.output = I3BarOutput(self.theme)
|
|
||||||
self.expectedStart = json.dumps({"version": 1, "click_events": True}) + "[\n"
|
|
||||||
self.expectedStop = "]\n"
|
|
||||||
self.someWidget = MockWidget("foo bar baz")
|
|
||||||
self.anyModule = MockModule(None, None)
|
|
||||||
self.anyColor = "#ababab"
|
|
||||||
self.anotherColor = "#cccccc"
|
|
||||||
|
|
||||||
@mock.patch("sys.stdout", new_callable=StringIO)
|
|
||||||
def test_start(self, stdout):
|
|
||||||
self.output.start()
|
|
||||||
self.assertEquals(self.expectedStart, stdout.getvalue())
|
|
||||||
|
|
||||||
@mock.patch("sys.stdout", new_callable=StringIO)
|
|
||||||
def test_stop(self, stdout):
|
|
||||||
self.output.stop()
|
|
||||||
self.assertEquals(self.expectedStop, stdout.getvalue())
|
|
||||||
|
|
||||||
@mock.patch("sys.stdout", new_callable=StringIO)
|
|
||||||
def test_draw_single_widget(self, stdout):
|
|
||||||
self.output.draw(self.someWidget, self.anyModule)
|
|
||||||
self.output.flush()
|
|
||||||
result = json.loads(stdout.getvalue())[0]
|
|
||||||
self.assertEquals(result["full_text"], self.someWidget.full_text())
|
|
||||||
|
|
||||||
@mock.patch("sys.stdout", new_callable=StringIO)
|
|
||||||
def test_draw_multiple_widgets(self, stdout):
|
|
||||||
for widget in [self.someWidget, self.someWidget]:
|
|
||||||
self.output.draw(widget, self.anyModule)
|
|
||||||
self.output.flush()
|
|
||||||
result = json.loads(stdout.getvalue())
|
|
||||||
for res in result:
|
|
||||||
self.assertEquals(res["full_text"], self.someWidget.full_text())
|
|
||||||
|
|
||||||
@mock.patch("sys.stdout", new_callable=StringIO)
|
|
||||||
def test_begin(self, stdout):
|
|
||||||
self.output.begin()
|
|
||||||
self.assertEquals("", stdout.getvalue())
|
|
||||||
|
|
||||||
@mock.patch("sys.stdout", new_callable=StringIO)
|
|
||||||
def test_end(self, stdout):
|
|
||||||
self.output.end()
|
|
||||||
self.assertEquals(",\n", stdout.getvalue())
|
|
||||||
|
|
||||||
@mock.patch("sys.stdout", new_callable=StringIO)
|
|
||||||
def test_prefix(self, stdout):
|
|
||||||
self.theme.attr_prefix = " - "
|
|
||||||
self.output.draw(self.someWidget, self.anyModule)
|
|
||||||
self.output.flush()
|
|
||||||
result = json.loads(stdout.getvalue())[0]
|
|
||||||
self.assertEquals(result["full_text"], "{}{}".format(
|
|
||||||
self.theme.prefix(self.someWidget), self.someWidget.full_text())
|
|
||||||
)
|
|
||||||
|
|
||||||
@mock.patch("sys.stdout", new_callable=StringIO)
|
|
||||||
def test_suffix(self, stdout):
|
|
||||||
self.theme.attr_suffix = " - "
|
|
||||||
self.output.draw(self.someWidget, self.anyModule)
|
|
||||||
self.output.flush()
|
|
||||||
result = json.loads(stdout.getvalue())[0]
|
|
||||||
self.assertEquals(result["full_text"], "{}{}".format(
|
|
||||||
self.someWidget.full_text(), self.theme.suffix(self.someWidget))
|
|
||||||
)
|
|
||||||
|
|
||||||
@mock.patch("sys.stdout", new_callable=StringIO)
|
|
||||||
def test_bothfix(self, stdout):
|
|
||||||
self.theme.attr_suffix = " - "
|
|
||||||
self.theme.attr_prefix = " * "
|
|
||||||
self.output.draw(self.someWidget, self.anyModule)
|
|
||||||
self.output.flush()
|
|
||||||
result = json.loads(stdout.getvalue())[0]
|
|
||||||
self.assertEquals(result["full_text"], "{}{}{}".format(
|
|
||||||
self.theme.prefix(self.someWidget),
|
|
||||||
self.someWidget.full_text(),
|
|
||||||
self.theme.suffix(self.someWidget)
|
|
||||||
))
|
|
||||||
|
|
||||||
@mock.patch("sys.stdout", new_callable=StringIO)
|
|
||||||
def test_colors(self, stdout):
|
|
||||||
self.theme.attr_fg = self.anyColor
|
|
||||||
self.theme.attr_bg = self.anotherColor
|
|
||||||
self.output.draw(self.someWidget, self.anyModule)
|
|
||||||
self.output.flush()
|
|
||||||
result = json.loads(stdout.getvalue())[0]
|
|
||||||
self.assertEquals(result["color"], self.anyColor)
|
|
||||||
self.assertEquals(result["background"], self.anotherColor)
|
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
|
@ -1,50 +0,0 @@
|
||||||
# pylint: disable=C0103,C0111,W0703
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
from bumblebee.engine import Module
|
|
||||||
from bumblebee.config import Config
|
|
||||||
from tests.util import MockWidget
|
|
||||||
|
|
||||||
class TestModule(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.widget = MockWidget("foo")
|
|
||||||
self.config = Config()
|
|
||||||
self.moduleWithoutWidgets = Module(engine=None, widgets=None)
|
|
||||||
self.moduleWithOneWidget = Module(engine=None, widgets=self.widget)
|
|
||||||
self.moduleWithMultipleWidgets = Module(engine=None,
|
|
||||||
widgets=[self.widget, self.widget, self.widget]
|
|
||||||
)
|
|
||||||
|
|
||||||
self.anyConfigName = "cfg"
|
|
||||||
self.anotherConfigName = "cfg2"
|
|
||||||
self.anyModule = Module(engine=None, widgets=self.widget, config={
|
|
||||||
"name": self.anyConfigName, "config": self.config
|
|
||||||
})
|
|
||||||
self.anotherModule = Module(engine=None, widgets=self.widget, config={
|
|
||||||
"name": self.anotherConfigName, "config": self.config
|
|
||||||
})
|
|
||||||
self.anyKey = "some-parameter"
|
|
||||||
self.anyValue = "value"
|
|
||||||
self.anotherValue = "another-value"
|
|
||||||
self.emptyKey = "i-do-not-exist"
|
|
||||||
self.config.set("{}.{}".format(self.anyConfigName, self.anyKey), self.anyValue)
|
|
||||||
self.config.set("{}.{}".format(self.anotherConfigName, self.anyKey), self.anotherValue)
|
|
||||||
|
|
||||||
def test_empty_widgets(self):
|
|
||||||
self.assertEquals(self.moduleWithoutWidgets.widgets(), [])
|
|
||||||
|
|
||||||
def test_single_widget(self):
|
|
||||||
self.assertEquals(self.moduleWithOneWidget.widgets(), [self.widget])
|
|
||||||
|
|
||||||
def test_multiple_widgets(self):
|
|
||||||
for widget in self.moduleWithMultipleWidgets.widgets():
|
|
||||||
self.assertEquals(widget, self.widget)
|
|
||||||
|
|
||||||
def test_parameters(self):
|
|
||||||
self.assertEquals(self.anyModule.parameter(self.anyKey), self.anyValue)
|
|
||||||
self.assertEquals(self.anotherModule.parameter(self.anyKey), self.anotherValue)
|
|
||||||
|
|
||||||
def test_default_parameters(self):
|
|
||||||
self.assertEquals(self.anyModule.parameter(self.emptyKey), None)
|
|
||||||
self.assertEquals(self.anyModule.parameter(self.emptyKey, self.anyValue), self.anyValue)
|
|
|
@ -1,24 +0,0 @@
|
||||||
# pylint: disable=C0103,C0111,W0703
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
from bumblebee.store import Store
|
|
||||||
|
|
||||||
class TestStore(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.store = Store()
|
|
||||||
self.anyKey = "some-key"
|
|
||||||
self.anyValue = "some-value"
|
|
||||||
self.unsetKey = "invalid-key"
|
|
||||||
|
|
||||||
def test_set_value(self):
|
|
||||||
self.store.set(self.anyKey, self.anyValue)
|
|
||||||
self.assertEquals(self.store.get(self.anyKey), self.anyValue)
|
|
||||||
|
|
||||||
def test_get_invalid_value(self):
|
|
||||||
result = self.store.get(self.unsetKey)
|
|
||||||
self.assertEquals(result, None)
|
|
||||||
|
|
||||||
def test_get_invalid_with_default_value(self):
|
|
||||||
result = self.store.get(self.unsetKey, self.anyValue)
|
|
||||||
self.assertEquals(result, self.anyValue)
|
|
|
@ -1,115 +0,0 @@
|
||||||
# pylint: disable=C0103,C0111,W0703
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
from bumblebee.theme import Theme
|
|
||||||
from bumblebee.error import ThemeLoadError
|
|
||||||
from tests.util import MockWidget
|
|
||||||
|
|
||||||
class TestTheme(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.nonexistentThemeName = "no-such-theme"
|
|
||||||
self.invalidThemeName = "test_invalid"
|
|
||||||
self.validThemeName = "test"
|
|
||||||
self.themedWidget = MockWidget("bla")
|
|
||||||
self.theme = Theme(self.validThemeName)
|
|
||||||
self.cycleTheme = Theme("test_cycle")
|
|
||||||
self.anyWidget = MockWidget("bla")
|
|
||||||
self.anotherWidget = MockWidget("blub")
|
|
||||||
|
|
||||||
data = self.theme.data()
|
|
||||||
self.widgetTheme = "test-widget"
|
|
||||||
self.themedWidget.module = self.widgetTheme
|
|
||||||
self.defaultColor = data["defaults"]["fg"]
|
|
||||||
self.defaultBgColor = data["defaults"]["bg"]
|
|
||||||
self.widgetColor = data[self.widgetTheme]["fg"]
|
|
||||||
self.widgetBgColor = data[self.widgetTheme]["bg"]
|
|
||||||
self.defaultPrefix = data["defaults"]["prefix"]
|
|
||||||
self.defaultSuffix = data["defaults"]["suffix"]
|
|
||||||
self.widgetPrefix = data[self.widgetTheme]["prefix"]
|
|
||||||
self.widgetSuffix = data[self.widgetTheme]["suffix"]
|
|
||||||
|
|
||||||
def test_load_valid_theme(self):
|
|
||||||
try:
|
|
||||||
Theme(self.validThemeName)
|
|
||||||
except Exception as e:
|
|
||||||
self.fail(e)
|
|
||||||
|
|
||||||
def test_load_nonexistent_theme(self):
|
|
||||||
with self.assertRaises(ThemeLoadError):
|
|
||||||
Theme(self.nonexistentThemeName)
|
|
||||||
|
|
||||||
def test_load_invalid_theme(self):
|
|
||||||
with self.assertRaises(ThemeLoadError):
|
|
||||||
Theme(self.invalidThemeName)
|
|
||||||
|
|
||||||
def test_default_prefix(self):
|
|
||||||
self.assertEquals(self.theme.prefix(self.anyWidget), self.defaultPrefix)
|
|
||||||
|
|
||||||
def test_default_suffix(self):
|
|
||||||
self.assertEquals(self.theme.suffix(self.anyWidget), self.defaultSuffix)
|
|
||||||
|
|
||||||
def test_widget_prefix(self):
|
|
||||||
self.assertEquals(self.theme.prefix(self.themedWidget), self.widgetPrefix)
|
|
||||||
|
|
||||||
def test_widget_fg(self):
|
|
||||||
self.assertEquals(self.theme.fg(self.anyWidget), self.defaultColor)
|
|
||||||
self.anyWidget.module = self.widgetTheme
|
|
||||||
self.assertEquals(self.theme.fg(self.anyWidget), self.widgetColor)
|
|
||||||
|
|
||||||
def test_widget_bg(self):
|
|
||||||
self.assertEquals(self.theme.bg(self.anyWidget), self.defaultBgColor)
|
|
||||||
self.anyWidget.module = self.widgetTheme
|
|
||||||
self.assertEquals(self.theme.bg(self.anyWidget), self.widgetBgColor)
|
|
||||||
|
|
||||||
def test_absent_cycle(self):
|
|
||||||
theme = self.theme
|
|
||||||
try:
|
|
||||||
theme.fg(self.anyWidget)
|
|
||||||
theme.fg(self.anotherWidget)
|
|
||||||
except Exception as e:
|
|
||||||
self.fail(e)
|
|
||||||
|
|
||||||
def test_reset(self):
|
|
||||||
theme = self.cycleTheme
|
|
||||||
data = theme.data()
|
|
||||||
theme.reset()
|
|
||||||
self.assertEquals(theme.fg(self.anyWidget), data["cycle"][0]["fg"])
|
|
||||||
self.assertEquals(theme.fg(self.anotherWidget), data["cycle"][1]["fg"])
|
|
||||||
theme.reset()
|
|
||||||
self.assertEquals(theme.fg(self.anyWidget), data["cycle"][0]["fg"])
|
|
||||||
|
|
||||||
def test_separator_block_width(self):
|
|
||||||
theme = self.theme
|
|
||||||
data = theme.data()
|
|
||||||
|
|
||||||
self.assertEquals(theme.separator_block_width(self.anyWidget),
|
|
||||||
data["defaults"]["separator-block-width"]
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_separator(self):
|
|
||||||
for theme in [self.theme, self.cycleTheme]:
|
|
||||||
theme.reset()
|
|
||||||
prev_bg = theme.bg(self.anyWidget)
|
|
||||||
theme.bg(self.anotherWidget)
|
|
||||||
|
|
||||||
self.assertEquals(theme.separator_fg(self.anotherWidget), theme.bg(self.anotherWidget))
|
|
||||||
self.assertEquals(theme.separator_bg(self.anotherWidget), prev_bg)
|
|
||||||
|
|
||||||
def test_state(self):
|
|
||||||
theme = self.theme
|
|
||||||
data = theme.data()
|
|
||||||
|
|
||||||
self.assertEquals(theme.fg(self.anyWidget), data["defaults"]["fg"])
|
|
||||||
self.assertEquals(theme.bg(self.anyWidget), data["defaults"]["bg"])
|
|
||||||
|
|
||||||
self.anyWidget.attr_state = ["critical"]
|
|
||||||
self.assertEquals(theme.fg(self.anyWidget), data["defaults"]["critical"]["fg"])
|
|
||||||
self.assertEquals(theme.bg(self.anyWidget), data["defaults"]["critical"]["bg"])
|
|
||||||
|
|
||||||
self.themedWidget.attr_state = ["critical"]
|
|
||||||
self.assertEquals(theme.fg(self.themedWidget), data[self.widgetTheme]["critical"]["fg"])
|
|
||||||
# if elements are missing in the state theme, they are taken from the
|
|
||||||
# widget theme instead (i.e. no fallback to a more general state theme)
|
|
||||||
self.assertEquals(theme.bg(self.themedWidget), data[self.widgetTheme]["bg"])
|
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
|
@ -1,18 +1,27 @@
|
||||||
# pylint: disable=C0103,C0111
|
# pylint: disable=C0103,C0111
|
||||||
|
|
||||||
|
import mock
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
import mocks
|
||||||
|
|
||||||
from bumblebee.util import *
|
from bumblebee.util import *
|
||||||
|
|
||||||
class TestUtil(unittest.TestCase):
|
class TestUtil(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.popen = mocks.MockPopen("bumblebee.util")
|
||||||
|
self.some_command_with_args = "sample-command -a -b -c"
|
||||||
|
self.some_utf8 = "some string".encode("utf-8")
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self.popen.cleanup()
|
||||||
|
|
||||||
def test_bytefmt(self):
|
def test_bytefmt(self):
|
||||||
value = 10
|
self.assertEquals(bytefmt(10), "10.00B")
|
||||||
display = 10
|
self.assertEquals(bytefmt(15*1024), "15.00KiB")
|
||||||
units = [ "B", "KiB", "MiB", "GiB" ]
|
self.assertEquals(bytefmt(20*1024*1024), "20.00MiB")
|
||||||
for unit in units:
|
self.assertEquals(bytefmt(22*1024*1024*1024), "22.00GiB")
|
||||||
self.assertEquals(bytefmt(value), "{:.2f}{}".format(display, unit))
|
self.assertEquals(bytefmt(35*1024*1024*1024*1024), "35840.00GiB")
|
||||||
value *= 1024
|
|
||||||
self.assertEquals(bytefmt(value), "{:.2f}GiB".format(display*1024))
|
|
||||||
|
|
||||||
def test_durationfmt(self):
|
def test_durationfmt(self):
|
||||||
self.assertEquals(durationfmt(00), "00:00")
|
self.assertEquals(durationfmt(00), "00:00")
|
||||||
|
@ -22,4 +31,20 @@ class TestUtil(unittest.TestCase):
|
||||||
self.assertEquals(durationfmt(3600), "01:00:00")
|
self.assertEquals(durationfmt(3600), "01:00:00")
|
||||||
self.assertEquals(durationfmt(7265), "02:01:05")
|
self.assertEquals(durationfmt(7265), "02:01:05")
|
||||||
|
|
||||||
|
def test_execute(self):
|
||||||
|
execute(self.some_command_with_args)
|
||||||
|
self.assertTrue(self.popen.mock.popen.called)
|
||||||
|
self.popen.mock.popen.assert_call(self.some_command_with_args)
|
||||||
|
self.assertTrue(self.popen.mock.communicate.called)
|
||||||
|
|
||||||
|
def test_execute_utf8(self):
|
||||||
|
self.popen.mock.communicate.return_value = [ self.some_utf8, None ]
|
||||||
|
self.test_execute()
|
||||||
|
|
||||||
|
def test_execute_error(self):
|
||||||
|
self.popen.mock.returncode = 1
|
||||||
|
|
||||||
|
with self.assertRaises(RuntimeError):
|
||||||
|
execute(self.some_command_with_args)
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
|
|
162
tests/util.py
162
tests/util.py
|
@ -1,162 +0,0 @@
|
||||||
# pylint: disable=C0103,C0111,W0613
|
|
||||||
|
|
||||||
import json
|
|
||||||
import shlex
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from bumblebee.output import Widget
|
|
||||||
|
|
||||||
def assertWidgetAttributes(test, widget):
|
|
||||||
test.assertTrue(isinstance(widget, Widget))
|
|
||||||
test.assertTrue(hasattr(widget, "full_text"))
|
|
||||||
|
|
||||||
def assertPopen(output, cmd):
|
|
||||||
res = shlex.split(cmd)
|
|
||||||
output.assert_any_call(res,
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.STDOUT
|
|
||||||
)
|
|
||||||
|
|
||||||
def assertStateContains(test, module, state):
|
|
||||||
for widget in module.widgets():
|
|
||||||
widget.link_module(module)
|
|
||||||
module.update(module.widgets())
|
|
||||||
test.assertTrue(state in module.widgets()[0].state())
|
|
||||||
|
|
||||||
class MockEpoll(object):
|
|
||||||
def register(self, fileno, event):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def poll(self, timeout):
|
|
||||||
return [(1,2)]
|
|
||||||
|
|
||||||
def unregister(self, fileno):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def assertMouseEvent(mock_input, mock_output, mock_select, engine, module, button, cmd, instance_id=None):
|
|
||||||
mock_input.readline.return_value = json.dumps({
|
|
||||||
"name": module.id if module else "test",
|
|
||||||
"button": button,
|
|
||||||
"instance": instance_id
|
|
||||||
})
|
|
||||||
mock_input.fileno.return_value = 1
|
|
||||||
mock_select.return_value = MockEpoll()
|
|
||||||
engine.input.start()
|
|
||||||
engine.input.stop()
|
|
||||||
mock_input.readline.assert_any_call()
|
|
||||||
if cmd:
|
|
||||||
assertPopen(mock_output, cmd)
|
|
||||||
|
|
||||||
class MockInput(object):
|
|
||||||
def __init__(self):
|
|
||||||
self._callbacks = {}
|
|
||||||
def start(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def get_callback(self, uid):
|
|
||||||
return self._callbacks.get(uid, None)
|
|
||||||
|
|
||||||
def register_callback(self, obj, button, cmd):
|
|
||||||
if not obj:
|
|
||||||
return
|
|
||||||
self._callbacks[obj.id] = {
|
|
||||||
"button": button,
|
|
||||||
"command": cmd,
|
|
||||||
}
|
|
||||||
|
|
||||||
class MockEngine(object):
|
|
||||||
def __init__(self):
|
|
||||||
self.input = MockInput()
|
|
||||||
|
|
||||||
class MockConfig(object):
|
|
||||||
def __init__(self):
|
|
||||||
self._data = {}
|
|
||||||
|
|
||||||
def get(self, name, default):
|
|
||||||
if name in self._data:
|
|
||||||
return self._data[name]
|
|
||||||
return default
|
|
||||||
|
|
||||||
def set(self, name, value):
|
|
||||||
self._data[name] = value
|
|
||||||
|
|
||||||
class MockOutput(object):
|
|
||||||
def start(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def draw(self, widget, engine, module):
|
|
||||||
engine.stop()
|
|
||||||
|
|
||||||
def begin(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def flush(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def end(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class MockModule(object):
|
|
||||||
def __init__(self, engine=None, config=None):
|
|
||||||
self.id = None
|
|
||||||
|
|
||||||
class MockWidget(Widget):
|
|
||||||
def __init__(self, text):
|
|
||||||
super(MockWidget, self).__init__(text)
|
|
||||||
self._text = text
|
|
||||||
self.module = None
|
|
||||||
self.attr_state = ["state-default"]
|
|
||||||
self.id = "none"
|
|
||||||
|
|
||||||
def state(self):
|
|
||||||
return self.attr_state
|
|
||||||
|
|
||||||
def update(self, widgets):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def full_text(self):
|
|
||||||
return self._text
|
|
||||||
|
|
||||||
class MockTheme(object):
|
|
||||||
def __init__(self):
|
|
||||||
self.attr_prefix = None
|
|
||||||
self.attr_suffix = None
|
|
||||||
self.attr_fg = None
|
|
||||||
self.attr_bg = None
|
|
||||||
self.attr_separator = None
|
|
||||||
self.attr_separator_block_width = 0
|
|
||||||
|
|
||||||
def padding(self, widget):
|
|
||||||
return ""
|
|
||||||
|
|
||||||
def reset(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def separator_block_width(self, widget):
|
|
||||||
return self.attr_separator_block_width
|
|
||||||
|
|
||||||
def separator(self, widget):
|
|
||||||
return self.attr_separator
|
|
||||||
|
|
||||||
def prefix(self, widget, default=None):
|
|
||||||
return self.attr_prefix
|
|
||||||
|
|
||||||
def suffix(self, widget, default=None):
|
|
||||||
return self.attr_suffix
|
|
||||||
|
|
||||||
def fg(self, widget):
|
|
||||||
return self.attr_fg
|
|
||||||
|
|
||||||
def bg(self, widget):
|
|
||||||
return self.attr_bg
|
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
Loading…
Reference in a new issue