2
# -*- mode: python; coding: utf-8; after-save-hook: (lambda () (let ((command (if (and (boundp 'tramp-file-name-structure) (string-match (car tramp-file-name-structure) (buffer-file-name))) (tramp-file-name-localname (tramp-dissect-file-name (buffer-file-name))) (buffer-file-name)))) (if (= (shell-command (format "%s --check" (shell-quote-argument command)) "*Test*") 0) (let ((w (get-buffer-window "*Test*"))) (if w (delete-window w)) (kill-buffer "*Test*")) (display-buffer "*Test*")))); -*-
2
# -*- after-save-hook: (lambda () (let ((command (if (fboundp 'file-local-name) (file-local-name (buffer-file-name)) (or (file-remote-p (buffer-file-name) 'localname) (buffer-file-name))))) (if (= (progn (if (get-buffer "*Test*") (kill-buffer "*Test*")) (process-file-shell-command (format "%s --check" (shell-quote-argument command)) nil "*Test*")) 0) (let ((w (get-buffer-window "*Test*"))) (if w (delete-window w))) (progn (with-current-buffer "*Test*" (compilation-mode)) (display-buffer "*Test*" '(display-buffer-in-side-window)))))); coding: utf-8 -*-
4
4
# Mandos Monitor - Control and monitor the Mandos server
250
253
def rfc3339_duration_to_delta(duration):
251
254
"""Parse an RFC 3339 "duration" and return a datetime.timedelta
253
>>> rfc3339_duration_to_delta("P7D")
254
datetime.timedelta(7)
255
>>> rfc3339_duration_to_delta("PT60S")
256
datetime.timedelta(0, 60)
257
>>> rfc3339_duration_to_delta("PT60M")
258
datetime.timedelta(0, 3600)
259
>>> rfc3339_duration_to_delta("P60M")
260
datetime.timedelta(1680)
261
>>> rfc3339_duration_to_delta("PT24H")
262
datetime.timedelta(1)
263
>>> rfc3339_duration_to_delta("P1W")
264
datetime.timedelta(7)
265
>>> rfc3339_duration_to_delta("PT5M30S")
266
datetime.timedelta(0, 330)
267
>>> rfc3339_duration_to_delta("P1DT3M20S")
268
datetime.timedelta(1, 200)
256
>>> rfc3339_duration_to_delta("P7D") == datetime.timedelta(7)
258
>>> rfc3339_duration_to_delta("PT60S") == datetime.timedelta(0, 60)
260
>>> rfc3339_duration_to_delta("PT60M") == datetime.timedelta(hours=1)
263
>>> rfc3339_duration_to_delta("P60M") == datetime.timedelta(1680)
265
>>> rfc3339_duration_to_delta("PT24H") == datetime.timedelta(1)
267
>>> rfc3339_duration_to_delta("P1W") == datetime.timedelta(7)
269
>>> rfc3339_duration_to_delta("PT5M30S") == datetime.timedelta(0, 330)
271
>>> rfc3339_duration_to_delta("P1DT3M20S") == datetime.timedelta(1, 200)
269
273
>>> # Can not be empty:
270
274
>>> rfc3339_duration_to_delta("")
271
275
Traceback (most recent call last):
381
385
"""Parse an interval string as documented by Mandos before 1.6.1,
382
386
and return a datetime.timedelta
384
>>> parse_pre_1_6_1_interval('7d')
385
datetime.timedelta(7)
386
>>> parse_pre_1_6_1_interval('60s')
387
datetime.timedelta(0, 60)
388
>>> parse_pre_1_6_1_interval('60m')
389
datetime.timedelta(0, 3600)
390
>>> parse_pre_1_6_1_interval('24h')
391
datetime.timedelta(1)
392
>>> parse_pre_1_6_1_interval('1w')
393
datetime.timedelta(7)
394
>>> parse_pre_1_6_1_interval('5m 30s')
395
datetime.timedelta(0, 330)
396
>>> parse_pre_1_6_1_interval('')
397
datetime.timedelta(0)
388
>>> parse_pre_1_6_1_interval('7d') == datetime.timedelta(days=7)
390
>>> parse_pre_1_6_1_interval('60s') == datetime.timedelta(0, 60)
392
>>> parse_pre_1_6_1_interval('60m') == datetime.timedelta(hours=1)
394
>>> parse_pre_1_6_1_interval('24h') == datetime.timedelta(days=1)
396
>>> parse_pre_1_6_1_interval('1w') == datetime.timedelta(days=7)
398
>>> parse_pre_1_6_1_interval('5m 30s') == datetime.timedelta(0, 330)
400
>>> parse_pre_1_6_1_interval('') == datetime.timedelta(0)
398
402
>>> # Ignore unknown characters, allow any order and repetitions
399
>>> parse_pre_1_6_1_interval('2dxy7zz11y3m5m')
400
datetime.timedelta(2, 480, 18000)
403
>>> parse_pre_1_6_1_interval('2dxy7zz11y3m5m') == datetime.timedelta(2, 480, 18000)
571
575
for key, subval in value.items()}
578
def set_client_property(self, objectpath, key, value):
580
if not isinstance(value, bytes):
581
value = value.encode("utf-8")
582
value = self.dbus_python.ByteArray(value)
583
return self.set_property(self.busname, objectpath,
584
self.client_interface, key,
575
class SilenceLogger(object):
576
588
"Simple context manager to silence a particular logger"
577
589
def __init__(self, loggername):
578
590
self.logger = logging.getLogger(loggername)
706
class command(object):
707
719
"""A namespace for command classes"""
710
722
"""Abstract base class for commands"""
711
723
def run(self, clients, bus=None):
712
724
"""Normal commands should implement run_on_one_client(),
1302
1314
class Test_dbus_python_adapter_SystemBus(TestCaseWithAssertLogs):
1304
1316
def MockDBusPython_func(self, func):
1305
class mock_dbus_python(object):
1317
class mock_dbus_python:
1306
1318
"""mock dbus-python module"""
1307
class exceptions(object):
1308
1320
"""Pseudo-namespace"""
1309
1321
class DBusException(Exception):
1311
class SystemBus(object):
1313
1325
def get_object(busname, objectpath):
1314
1326
DBusObject = collections.namedtuple(
1315
"DBusObject", ("methodname",))
1327
"DBusObject", ("methodname", "Set"))
1316
1328
def method(*args, **kwargs):
1317
1329
self.assertEqual({"dbus_interface":
1320
1332
return func(*args)
1321
return DBusObject(methodname=method)
1322
class Boolean(object):
1333
def set_property(interface, key, value,
1334
dbus_interface=None):
1336
"org.freedesktop.DBus.Properties",
1338
self.assertEqual("Secret", key)
1339
return func(interface, key, value,
1340
dbus_interface=dbus_interface)
1341
return DBusObject(methodname=method,
1323
1344
def __init__(self, value):
1324
1345
self.value = bool(value)
1325
1346
def __bool__(self):
1512
1535
# Make sure the dbus logger was suppressed
1513
1536
self.assertEqual(0, counting_handler.count)
1538
def test_Set_Secret_sends_bytearray(self):
1540
def func(*args, **kwargs):
1541
ret[0] = (args, kwargs)
1542
mock_dbus_python = self.MockDBusPython_func(func)
1543
bus = dbus_python_adapter.SystemBus(mock_dbus_python)
1544
bus.set_client_property("objectpath", "Secret", "value")
1545
expected_call = (("se.recompile.Mandos.Client", "Secret",
1546
mock_dbus_python.ByteArray(b"value")),
1548
"org.freedesktop.DBus.Properties"})
1549
self.assertEqual(expected_call, ret[0])
1550
if sys.version_info.major == 2:
1551
self.assertIsInstance(ret[0][0][-1],
1552
mock_dbus_python.ByteArray)
1515
1554
def test_get_object_converts_to_correct_exception(self):
1516
1555
bus = dbus_python_adapter.SystemBus(
1517
1556
self.fake_dbus_python_raises_exception_on_connect)
1519
1558
self.call_method(bus, "methodname", "busname",
1520
1559
"objectpath", "interface")
1522
class fake_dbus_python_raises_exception_on_connect(object):
1561
class fake_dbus_python_raises_exception_on_connect:
1523
1562
"""fake dbus-python module"""
1524
class exceptions(object):
1525
1564
"""Pseudo-namespace"""
1526
1565
class DBusException(Exception):
1537
1576
class Test_dbus_python_adapter_CachingBus(unittest.TestCase):
1538
class mock_dbus_python(object):
1577
class mock_dbus_python:
1539
1578
"""mock dbus-python modules"""
1540
class SystemBus(object):
1542
1581
def get_object(busname, objectpath):
1543
1582
return Unique()
1589
1628
class Test_pydbus_adapter_SystemBus(TestCaseWithAssertLogs):
1591
1630
def Stub_pydbus_func(self, func):
1592
class stub_pydbus(object):
1593
1632
"""stub pydbus module"""
1594
class SystemBus(object):
1596
1635
def get(busname, objectpath):
1597
1636
DBusObject = collections.namedtuple(
1643
1682
self.call_method(bus, "methodname", "busname",
1644
1683
"objectpath", "interface")
1646
class fake_pydbus_raises_exception_on_connect(object):
1685
class fake_pydbus_raises_exception_on_connect:
1647
1686
"""fake dbus-python module"""
1649
1688
def SystemBus(cls):
1653
1692
return Bus(get=get)
1655
1694
def test_set_property_uses_setattr(self):
1656
class Object(object):
1659
class pydbus_spy(object):
1660
class SystemBus(object):
1662
1701
def get(busname, objectpath):
1663
1702
return {"interface": obj}
1670
1709
def test_get_suppresses_xml_deprecation_warning(self):
1671
1710
if sys.version_info.major >= 3:
1673
class stub_pydbus_get(object):
1674
class SystemBus(object):
1712
class stub_pydbus_get:
1676
1715
def get(busname, objectpath):
1677
1716
warnings.warn_explicit(
1745
1784
self.assert_command_from_args(["--is-enabled", "client"],
1746
1785
command.IsEnabled)
1748
def assert_command_from_args(self, args, command_cls,
1787
def assert_command_from_args(self, args, command_cls, length=1,
1788
clients=None, **cmd_attrs):
1750
1789
"""Assert that parsing ARGS should result in an instance of
1751
1790
COMMAND_CLS with (optionally) all supplied attributes (CMD_ATTRS)."""
1752
1791
options = self.parser.parse_args(args)
1753
1792
check_option_syntax(self.parser, options)
1754
1793
commands = commands_from_options(options)
1755
self.assertEqual(1, len(commands))
1756
command = commands[0]
1757
self.assertIsInstance(command, command_cls)
1794
self.assertEqual(length, len(commands))
1795
for command in commands:
1796
if isinstance(command, command_cls):
1799
self.assertIsInstance(command, command_cls)
1800
if clients is not None:
1801
self.assertEqual(clients, options.client)
1758
1802
for key, value in cmd_attrs.items():
1759
1803
self.assertEqual(value, getattr(command, key))
1805
def assert_commands_from_args(self, args, commands, clients=None):
1806
for cmd in commands:
1807
self.assert_command_from_args(args, cmd,
1808
length=len(commands),
1761
1811
def test_is_enabled_short(self):
1762
1812
self.assert_command_from_args(["-V", "client"],
1763
1813
command.IsEnabled)
2007
def test_manual_page_example_1(self):
2008
self.assert_command_from_args("",
2013
def test_manual_page_example_2(self):
2014
self.assert_command_from_args(
2015
"--verbose foo1.example.org foo2.example.org".split(),
2016
command.PrintTable, clients=["foo1.example.org",
2017
"foo2.example.org"],
2020
def test_manual_page_example_3(self):
2021
self.assert_command_from_args("--enable --all".split(),
2025
def test_manual_page_example_4(self):
2026
self.assert_commands_from_args(
2027
("--timeout=PT5M --interval=PT1M foo1.example.org"
2028
" foo2.example.org").split(),
2029
[command.SetTimeout, command.SetInterval],
2030
clients=["foo1.example.org", "foo2.example.org"])
2032
def test_manual_page_example_5(self):
2033
self.assert_command_from_args("--approve --all".split(),
1957
2038
class TestCommand(unittest.TestCase):
1958
2039
"""Abstract class for tests of command classes"""