1028
1007
for client in self.clients:
1029
1008
self.assertFalse(client.attributes["Enabled"])
1031
class Unique(object):
1032
"""Class for objects which exist only to be unique objects, since
1033
unittest.mock.sentinel only exists in Python 3.3"""
1035
class TestPropertyCmd(TestCmd):
1036
"""Abstract class for tests of PropertyCmd classes"""
1038
if not hasattr(self, "command"):
1040
values_to_get = getattr(self, "values_to_get",
1042
for value_to_set, value_to_get in zip(self.values_to_set,
1044
for client in self.clients:
1045
old_value = client.attributes[self.property]
1046
self.assertNotIsInstance(old_value, Unique)
1047
client.attributes[self.property] = Unique()
1048
self.run_command(value_to_set, self.clients)
1049
for client in self.clients:
1050
value = client.attributes[self.property]
1051
self.assertNotIsInstance(value, Unique)
1052
self.assertEqual(value, value_to_get)
1053
def run_command(self, value, clients):
1054
self.command().run(None, clients)
1056
class TestBumpTimeoutCmd(TestPropertyCmd):
1057
command = BumpTimeoutCmd
1058
property = "LastCheckedOK"
1059
values_to_set = [""]
1061
class TestStartCheckerCmd(TestPropertyCmd):
1062
command = StartCheckerCmd
1063
property = "CheckerRunning"
1064
values_to_set = [dbus.Boolean(True)]
1066
class TestStopCheckerCmd(TestPropertyCmd):
1067
command = StopCheckerCmd
1068
property = "CheckerRunning"
1069
values_to_set = [dbus.Boolean(False)]
1071
class TestApproveByDefaultCmd(TestPropertyCmd):
1072
command = ApproveByDefaultCmd
1073
property = "ApprovedByDefault"
1074
values_to_set = [dbus.Boolean(True)]
1076
class TestDenyByDefaultCmd(TestPropertyCmd):
1077
command = DenyByDefaultCmd
1078
property = "ApprovedByDefault"
1079
values_to_set = [dbus.Boolean(False)]
1081
class TestValueArgumentPropertyCmd(TestPropertyCmd):
1082
"""Abstract class for tests of PropertyCmd classes using the
1083
ValueArgumentMixIn"""
1085
if type(self) is TestValueArgumentPropertyCmd:
1087
return super(TestValueArgumentPropertyCmd, self).runTest()
1088
def run_command(self, value, clients):
1089
self.command(value).run(None, clients)
1091
class TestSetCheckerCmd(TestValueArgumentPropertyCmd):
1092
command = SetCheckerCmd
1093
property = "Checker"
1094
values_to_set = ["", ":", "fping -q -- %s"]
1096
class TestSetHostCmd(TestValueArgumentPropertyCmd):
1097
command = SetHostCmd
1099
values_to_set = ["192.0.2.3", "foo.example.org"]
1101
class TestSetSecretCmd(TestValueArgumentPropertyCmd):
1102
command = SetSecretCmd
1104
values_to_set = [open("/dev/null", "rb"),
1105
io.BytesIO(b"secret\0xyzzy\nbar")]
1106
values_to_get = [b"", b"secret\0xyzzy\nbar"]
1108
class TestSetTimeoutCmd(TestValueArgumentPropertyCmd):
1109
command = SetTimeoutCmd
1110
property = "Timeout"
1111
values_to_set = [datetime.timedelta(),
1112
datetime.timedelta(minutes=5),
1113
datetime.timedelta(seconds=1),
1114
datetime.timedelta(weeks=1),
1115
datetime.timedelta(weeks=52)]
1116
values_to_get = [0, 300000, 1000, 604800000, 31449600000]
1118
class TestSetExtendedTimeoutCmd(TestValueArgumentPropertyCmd):
1119
command = SetExtendedTimeoutCmd
1120
property = "ExtendedTimeout"
1121
values_to_set = [datetime.timedelta(),
1122
datetime.timedelta(minutes=5),
1123
datetime.timedelta(seconds=1),
1124
datetime.timedelta(weeks=1),
1125
datetime.timedelta(weeks=52)]
1126
values_to_get = [0, 300000, 1000, 604800000, 31449600000]
1128
class TestSetIntervalCmd(TestValueArgumentPropertyCmd):
1129
command = SetIntervalCmd
1130
property = "Interval"
1131
values_to_set = [datetime.timedelta(),
1132
datetime.timedelta(minutes=5),
1133
datetime.timedelta(seconds=1),
1134
datetime.timedelta(weeks=1),
1135
datetime.timedelta(weeks=52)]
1136
values_to_get = [0, 300000, 1000, 604800000, 31449600000]
1138
class TestSetApprovalDelayCmd(TestValueArgumentPropertyCmd):
1139
command = SetApprovalDelayCmd
1140
property = "ApprovalDelay"
1141
values_to_set = [datetime.timedelta(),
1142
datetime.timedelta(minutes=5),
1143
datetime.timedelta(seconds=1),
1144
datetime.timedelta(weeks=1),
1145
datetime.timedelta(weeks=52)]
1146
values_to_get = [0, 300000, 1000, 604800000, 31449600000]
1148
class TestSetApprovalDurationCmd(TestValueArgumentPropertyCmd):
1149
command = SetApprovalDurationCmd
1150
property = "ApprovalDuration"
1151
values_to_set = [datetime.timedelta(),
1152
datetime.timedelta(minutes=5),
1153
datetime.timedelta(seconds=1),
1154
datetime.timedelta(weeks=1),
1155
datetime.timedelta(weeks=52)]
1156
values_to_get = [0, 300000, 1000, 604800000, 31449600000]
1158
class Test_command_from_options(unittest.TestCase):
1160
self.parser = argparse.ArgumentParser()
1161
add_command_line_options(self.parser)
1162
def assert_command_from_args(self, args, command_cls, **cmd_attrs):
1163
"""Assert that parsing ARGS should result in an instance of
1164
COMMAND_CLS with (optionally) all supplied attributes (CMD_ATTRS)."""
1165
options = self.parser.parse_args(args)
1166
check_option_syntax(self.parser, options)
1167
commands = commands_from_options(options)
1168
self.assertEqual(len(commands), 1)
1169
command = commands[0]
1170
self.assertIsInstance(command, command_cls)
1171
for key, value in cmd_attrs.items():
1172
self.assertEqual(getattr(command, key), value)
1173
def test_print_table(self):
1174
self.assert_command_from_args([], PrintTableCmd,
1177
def test_print_table_verbose(self):
1178
self.assert_command_from_args(["--verbose"], PrintTableCmd,
1181
def test_print_table_verbose_short(self):
1182
self.assert_command_from_args(["-v"], PrintTableCmd,
1185
def test_enable(self):
1186
self.assert_command_from_args(["--enable", "foo"], EnableCmd)
1188
def test_enable_short(self):
1189
self.assert_command_from_args(["-e", "foo"], EnableCmd)
1191
def test_disable(self):
1192
self.assert_command_from_args(["--disable", "foo"],
1195
def test_disable_short(self):
1196
self.assert_command_from_args(["-d", "foo"], DisableCmd)
1198
def test_bump_timeout(self):
1199
self.assert_command_from_args(["--bump-timeout", "foo"],
1202
def test_bump_timeout_short(self):
1203
self.assert_command_from_args(["-b", "foo"], BumpTimeoutCmd)
1205
def test_start_checker(self):
1206
self.assert_command_from_args(["--start-checker", "foo"],
1209
def test_stop_checker(self):
1210
self.assert_command_from_args(["--stop-checker", "foo"],
1213
def test_remove(self):
1214
self.assert_command_from_args(["--remove", "foo"],
1217
def test_remove_short(self):
1218
self.assert_command_from_args(["-r", "foo"], RemoveCmd)
1220
def test_checker(self):
1221
self.assert_command_from_args(["--checker", ":", "foo"],
1222
SetCheckerCmd, value_to_set=":")
1224
def test_checker_empty(self):
1225
self.assert_command_from_args(["--checker", "", "foo"],
1226
SetCheckerCmd, value_to_set="")
1228
def test_checker_short(self):
1229
self.assert_command_from_args(["-c", ":", "foo"],
1230
SetCheckerCmd, value_to_set=":")
1232
def test_timeout(self):
1233
self.assert_command_from_args(["--timeout", "PT5M", "foo"],
1235
value_to_set=300000)
1237
def test_timeout_short(self):
1238
self.assert_command_from_args(["-t", "PT5M", "foo"],
1240
value_to_set=300000)
1242
def test_extended_timeout(self):
1243
self.assert_command_from_args(["--extended-timeout", "PT15M",
1245
SetExtendedTimeoutCmd,
1246
value_to_set=900000)
1248
def test_interval(self):
1249
self.assert_command_from_args(["--interval", "PT2M", "foo"],
1251
value_to_set=120000)
1253
def test_interval_short(self):
1254
self.assert_command_from_args(["-i", "PT2M", "foo"],
1256
value_to_set=120000)
1258
def test_approve_by_default(self):
1259
self.assert_command_from_args(["--approve-by-default", "foo"],
1260
ApproveByDefaultCmd)
1262
def test_deny_by_default(self):
1263
self.assert_command_from_args(["--deny-by-default", "foo"],
1266
def test_approval_delay(self):
1267
self.assert_command_from_args(["--approval-delay", "PT30S",
1268
"foo"], SetApprovalDelayCmd,
1271
def test_approval_duration(self):
1272
self.assert_command_from_args(["--approval-duration", "PT1S",
1273
"foo"], SetApprovalDurationCmd,
1276
def test_host(self):
1277
self.assert_command_from_args(["--host", "foo.example.org",
1279
value_to_set="foo.example.org")
1281
def test_host_short(self):
1282
self.assert_command_from_args(["-H", "foo.example.org",
1284
value_to_set="foo.example.org")
1286
def test_secret_devnull(self):
1287
self.assert_command_from_args(["--secret", os.path.devnull,
1288
"foo"], SetSecretCmd,
1291
def test_secret_tempfile(self):
1292
with tempfile.NamedTemporaryFile(mode="r+b") as f:
1293
value = b"secret\0xyzzy\nbar"
1296
self.assert_command_from_args(["--secret", f.name,
1297
"foo"], SetSecretCmd,
1300
def test_secret_devnull_short(self):
1301
self.assert_command_from_args(["-s", os.path.devnull, "foo"],
1302
SetSecretCmd, value_to_set=b"")
1304
def test_secret_tempfile_short(self):
1305
with tempfile.NamedTemporaryFile(mode="r+b") as f:
1306
value = b"secret\0xyzzy\nbar"
1309
self.assert_command_from_args(["-s", f.name, "foo"],
1313
def test_approve(self):
1314
self.assert_command_from_args(["--approve", "foo"],
1317
def test_approve_short(self):
1318
self.assert_command_from_args(["-A", "foo"], ApproveCmd)
1320
def test_deny(self):
1321
self.assert_command_from_args(["--deny", "foo"], DenyCmd)
1323
def test_deny_short(self):
1324
self.assert_command_from_args(["-D", "foo"], DenyCmd)
1326
def test_dump_json(self):
1327
self.assert_command_from_args(["--dump-json"], DumpJSONCmd)
1329
def test_is_enabled(self):
1330
self.assert_command_from_args(["--is-enabled", "foo"],
1333
def test_is_enabled_short(self):
1334
self.assert_command_from_args(["-V", "foo"], IsEnabledCmd)
1337
class Test_check_option_syntax(unittest.TestCase):
1338
# This mostly corresponds to the definition from has_actions() in
1339
# check_option_syntax()
1341
# The actual values set here are not that important, but we do
1342
# at least stick to the correct types, even though they are
1346
"bump_timeout": True,
1347
"start_checker": True,
1348
"stop_checker": True,
1352
"timeout": datetime.timedelta(),
1353
"extended_timeout": datetime.timedelta(),
1354
"interval": datetime.timedelta(),
1355
"approved_by_default": True,
1356
"approval_delay": datetime.timedelta(),
1357
"approval_duration": datetime.timedelta(),
1359
"secret": io.BytesIO(b"x"),
1365
self.parser = argparse.ArgumentParser()
1366
add_command_line_options(self.parser)
1368
@contextlib.contextmanager
1369
def assertParseError(self):
1370
with self.assertRaises(SystemExit) as e:
1371
with self.temporarily_suppress_stderr():
1373
# Exit code from argparse is guaranteed to be "2". Reference:
1374
# https://docs.python.org/3/library/argparse.html#exiting-methods
1375
self.assertEqual(e.exception.code, 2)
1378
@contextlib.contextmanager
1379
def temporarily_suppress_stderr():
1380
null = os.open(os.path.devnull, os.O_RDWR)
1381
stderrcopy = os.dup(sys.stderr.fileno())
1382
os.dup2(null, sys.stderr.fileno())
1388
os.dup2(stderrcopy, sys.stderr.fileno())
1389
os.close(stderrcopy)
1391
def check_option_syntax(self, options):
1392
check_option_syntax(self.parser, options)
1394
def test_actions_requires_client_or_all(self):
1395
for action, value in self.actions.items():
1396
options = self.parser.parse_args()
1397
setattr(options, action, value)
1398
with self.assertParseError():
1399
self.check_option_syntax(options)
1401
def test_actions_conflicts_with_verbose(self):
1402
for action, value in self.actions.items():
1403
options = self.parser.parse_args()
1404
setattr(options, action, value)
1405
options.verbose = True
1406
with self.assertParseError():
1407
self.check_option_syntax(options)
1409
def test_dump_json_conflicts_with_verbose(self):
1410
options = self.parser.parse_args()
1411
options.dump_json = True
1412
options.verbose = True
1413
with self.assertParseError():
1414
self.check_option_syntax(options)
1416
def test_dump_json_conflicts_with_action(self):
1417
for action, value in self.actions.items():
1418
options = self.parser.parse_args()
1419
setattr(options, action, value)
1420
options.dump_json = True
1421
with self.assertParseError():
1422
self.check_option_syntax(options)
1424
def test_all_can_not_be_alone(self):
1425
options = self.parser.parse_args()
1427
with self.assertParseError():
1428
self.check_option_syntax(options)
1430
def test_all_is_ok_with_any_action(self):
1431
for action, value in self.actions.items():
1432
options = self.parser.parse_args()
1433
setattr(options, action, value)
1435
self.check_option_syntax(options)
1437
def test_is_enabled_fails_without_client(self):
1438
options = self.parser.parse_args()
1439
options.is_enabled = True
1440
with self.assertParseError():
1441
self.check_option_syntax(options)
1443
def test_is_enabled_works_with_one_client(self):
1444
options = self.parser.parse_args()
1445
options.is_enabled = True
1446
options.client = ["foo"]
1447
self.check_option_syntax(options)
1449
def test_is_enabled_fails_with_two_clients(self):
1450
options = self.parser.parse_args()
1451
options.is_enabled = True
1452
options.client = ["foo", "barbar"]
1453
with self.assertParseError():
1454
self.check_option_syntax(options)
1458
1012
def should_only_run_tests():