Completed
Push — rhel8-branch ( ec2c10...32e3c1 )
by Matěj
18s queued 10s
created

test_rule_handling.password_data()   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nop 3
1
import pytest
2
3
import mock
4
5
try:
6
    from org_fedora_oscap import rule_handling, common
7
except ImportError as exc:
8
    pytestmark = pytest.mark.skip(
9
        "Unable to import modules, possibly due to bad version of Anaconda: {error}"
10
        .format(error=str(exc)))
11
12
13
@pytest.fixture()
14
def part_rules():
15
    rules = rule_handling.PartRules()
16
    rules.ensure_mount_point("/tmp")
17
    return rules
18
19
20
# simple tests, shouldn't raise exceptions
21
def test_part_rules_getitem(part_rules):
22
    part_rules["/tmp"]
23
24
25
def test_part_rules_setitem(part_rules):
26
    rule = rule_handling.PartRule("/var/log")
27
    part_rules["/var/log"] = rule
28
29
30
def test_part_rules_len(part_rules):
31
    assert len(part_rules) == 1
32
33
34
def test_part_rules_contains(part_rules):
35
    assert "/tmp" in part_rules
36
37
38
def test_part_rules_delitem(part_rules):
39
    del(part_rules["/tmp"])
40
    assert "/tmp" not in part_rules
41
42
43
@pytest.fixture()
44
def rule_data():
45
    return rule_handling.RuleData()
46
47
48
def test_rule_data_artificial(rule_data):
49
    rule_data.new_rule("  part /tmp --mountoptions=nodev,noauto")
50
    rule_data.new_rule("part /var/log  ")
51
    rule_data.new_rule(" passwd   --minlen=14 ")
52
    rule_data.new_rule("package --add=iptables")
53
    rule_data.new_rule(" package --add=firewalld --remove=telnet")
54
    rule_data.new_rule("package --remove=rlogin --remove=sshd")
55
    rule_data.new_rule("bootloader --passwd")
56
57
    # both partitions should appear in rule_data._part_rules
58
    assert "/tmp" in rule_data._part_rules
59
    assert "/var/log" in rule_data._part_rules
60
61
    # mount options should be parsed
62
    assert "nodev" in rule_data._part_rules["/tmp"]._mount_options
63
    assert "noauto" in rule_data._part_rules["/tmp"]._mount_options
64
65
    # no mount options for /var/log
66
    assert not rule_data._part_rules["/var/log"]._mount_options
67
68
    # minimal password length should be parsed and stored correctly
69
    assert rule_data._passwd_rules._minlen == 14
70
71
    # packages should be parsed correctly
72
    assert "iptables" in rule_data._package_rules._add_pkgs
73
    assert "firewalld" in rule_data._package_rules._add_pkgs
74
    assert "telnet" in rule_data._package_rules._remove_pkgs
75
    assert "rlogin" in rule_data._package_rules._remove_pkgs
76
    assert "sshd" in rule_data._package_rules._remove_pkgs
77
78
    # bootloader should require password
79
    assert rule_data._bootloader_rules._require_password
80
81
82
def test_rule_data_quoted_opt_values(rule_data):
83
    rule_data.new_rule('part /tmp --mountoptions="nodev,noauto"')
84
85
    assert "nodev" in rule_data._part_rules["/tmp"]._mount_options
86
    assert "noauto" in rule_data._part_rules["/tmp"]._mount_options
87
    assert '"' not in rule_data._part_rules["/tmp"]._mount_options
88
89
90
def test_rule_data_real_output(rule_data):
91
    output = """
92
    part /tmp
93
94
    part /tmp --mountoptions=nodev
95
    """
96
    for line in output.splitlines():
97
        rule_data.new_rule(line)
98
99
    assert "/tmp" in rule_data._part_rules
100
    assert "nodev" in rule_data._part_rules["/tmp"]._mount_options
101
102
    # should be stripped and merged
103
    assert str(rule_data._part_rules) == "part /tmp --mountoptions=nodev"
104
105
106
@pytest.fixture()
107
def ksdata_mock():
108
    return mock.Mock()
109
110
111
@pytest.fixture()
112
def storage_mock():
113
    return mock.Mock()
114
115
116
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
117
def test_evaluation_existing_part_must_exist_rules(
118
        proxy_getter, rule_data, ksdata_mock, storage_mock):
119
    rules = [
120
        "part /tmp",
121
        "part /",
122
    ]
123
    for rule in rules:
124
        rule_data.new_rule(rule)
125
126
    tmp_part_mock = mock.Mock()
127
    tmp_part_mock.format.options = "defaults"
128
    root_part_mock = mock.Mock()
129
    root_part_mock.format.options = "defaults"
130
131
    storage_mock.mountpoints = {
132
        "/tmp": tmp_part_mock,
133
        "/": root_part_mock,
134
    }
135
136
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
137
138
    # partitions exist --> no errors, warnings or additional info
139
    assert not messages
140
141
    # no additional mount options specified
142
    assert tmp_part_mock.format.options == "defaults"
143
    assert root_part_mock.format.options == "defaults"
144
145
146
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
147
def test_evaluation_nonexisting_part_must_exist(
148
        proxy_getter, rule_data, ksdata_mock, storage_mock):
149
    rules = [
150
        "part /tmp",
151
        "part /",
152
    ]
153
    for rule in rules:
154
        rule_data.new_rule(rule)
155
156
    tmp_part_mock = mock.Mock()
157
    tmp_part_mock.format.options = "defaults"
158
159
    storage_mock.mountpoints = {
160
        "/tmp": tmp_part_mock,
161
    }
162
163
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
164
165
    # / mount point missing --> one error
166
    assert len(messages) == 1
167
    assert messages[0].type == common.MESSAGE_TYPE_FATAL
168
169
    # error has to mention the mount point
170
    assert "/" in messages[0].text
171
172
173
def get_partition_mocks(mount_options):
174
    tmp_part_mock = mock.Mock()
175
    tmp_part_mock.format.options = mount_options["/tmp"]
176
    root_part_mock = mock.Mock()
177
    root_part_mock.format.options = mount_options["/"]
178
179
    partition_mocks = {
180
        "/tmp": tmp_part_mock,
181
        "/": root_part_mock,
182
    }
183
    return partition_mocks
184
185
186
def set_mount_options_of_actual_mount_points(
187
        storage_mock, mount_options, actual_mountpoints):
188
    storage_mock.mountpoints = {}
189
    for mountpoint, value in mount_options.items():
190
        if mountpoint in actual_mountpoints:
191
            storage_mock.mountpoints[mountpoint] = value
192
193
194
def get_messages_for_partition_rules(
195
        rule_data, ksdata_mock, storage_mock,
196
        rules,
197
        messages_evaluation_count=1,
198
        actual_mountpoints=("/tmp", "/"),
199
        mount_options=None,
200
        report_only=False,
201
        ):
202
203
    assert len(rules) == 2, \
204
        "We need rules for temp partition and root."
205
206
    if mount_options is None:
207
        mount_options = {
208
            "/": "defaults",
209
            "/tmp": "defaults",
210
        }
211
212
    for rule in rules:
213
        rule_data.new_rule(rule)
214
215
    mount_options = get_partition_mocks(mount_options)
216
217
    set_mount_options_of_actual_mount_points(storage_mock, mount_options, actual_mountpoints)
218
219
    messages = []
220
    for _ in range(messages_evaluation_count):
221
        messages = rule_data.eval_rules(ksdata_mock, storage_mock, report_only)
222
223
    return messages
224
225
226
def evaluation_add_mount_options(
227
        rule_data, ksdata_mock, storage_mock,
228
        messages_evaluation_count):
229
    rules = [
230
        "part /tmp --mountoptions=defaults,nodev",
231
        "part / --mountoptions=noauto",
232
    ]
233
234
    messages = get_messages_for_partition_rules(
235
        rule_data, ksdata_mock, storage_mock,
236
        rules, messages_evaluation_count)
237
238
    # two mount options added --> two info messages
239
    assert len(messages) == 2
240
    assert all(message.type == common.MESSAGE_TYPE_INFO for message in messages)
241
242
    # newly added mount options should be mentioned in the messages
243
    # together with their mount points
244
    nodev_found = False
245
    noauto_found = False
246
247
    for message in messages:
248
        if "'nodev'" in message.text:
249
            assert "/tmp" in message.text
250
            nodev_found = True
251
        elif "'noauto'" in message.text:
252
            assert "/" in message.text
253
            noauto_found = True
254
255
    assert all([nodev_found, noauto_found])
256
    assert storage_mock.mountpoints["/tmp"].format.options == "defaults,nodev"
257
    assert storage_mock.mountpoints["/"].format.options == "defaults,noauto"
258
259
260
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
261
def test_evaluation_add_mount_options(
262
        proxy_getter, rule_data, ksdata_mock, storage_mock):
263
    evaluation_add_mount_options(rule_data, ksdata_mock, storage_mock, 1)
264
265
266
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
267
def test_evaluation_add_mount_options_no_duplicates(
268
        proxy_getter, rule_data, ksdata_mock, storage_mock):
269
    evaluation_add_mount_options(rule_data, ksdata_mock, storage_mock, 2)
270
271
272
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
273
def test_evaluation_add_mount_options_report_only(
274
        proxy_getter, rule_data, ksdata_mock, storage_mock):
275
    rules = [
276
        "part /tmp --mountoptions=nodev",
277
        "part / --mountoptions=noauto",
278
    ]
279
    messages = get_messages_for_partition_rules(
280
        rule_data, ksdata_mock, storage_mock,
281
        rules, 1, report_only=True)
282
283
    # two mount options added --> two info messages
284
    assert len(messages) == 2
285
    assert messages[0].type == common.MESSAGE_TYPE_INFO
286
    assert messages[1].type == common.MESSAGE_TYPE_INFO
287
288
    # newly added mount options should be mentioned in the messages
289
    # together with their mount points
290
    nodev_found = False
291
    noauto_found = False
292
293
    for message in messages:
294
        if "'nodev'" in message.text:
295
            assert "/tmp" in message.text
296
            nodev_found = True
297
        elif "'noauto'" in message.text:
298
            assert "/" in message.text
299
            noauto_found = True
300
301
    assert all([nodev_found, noauto_found])
302
303
    # no changes should be made
304
    assert storage_mock.mountpoints["/tmp"].format.options == "defaults"
305
    assert storage_mock.mountpoints["/"].format.options == "defaults"
306
307
308
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
309
def test_evaluation_add_mount_option_prefix(
310
        proxy_getter, rule_data, ksdata_mock, storage_mock):
311
    rules = [
312
        "part /tmp --mountoptions=nodev",
313
        "part / --mountoptions=noauto",
314
    ]
315
    mount_options = {
316
        "/": "defaults",
317
        "/tmp": "defaults,nodevice",
318
    }
319
    messages = get_messages_for_partition_rules(
320
        rule_data, ksdata_mock, storage_mock,
321
        rules, mount_options=mount_options)
322
323
    # two mount options added (even though it is a prefix of another one)
324
    #   --> two info messages
325
    assert len(messages) == 2
326
    assert messages[0].type == common.MESSAGE_TYPE_INFO
327
    assert messages[1].type == common.MESSAGE_TYPE_INFO
328
329
    # the option should be added even though it is a prefix of another one
330
    assert storage_mock.mountpoints["/tmp"].format.options == "defaults,nodevice,nodev"
331
332
333
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
334
def test_evaluation_add_mount_options_nonexisting_part(
335
        proxy_getter, rule_data, ksdata_mock, storage_mock):
336
    rules = [
337
        "part /tmp --mountoptions=nodev",
338
        "part / --mountoptions=noauto",
339
    ]
340
    messages = get_messages_for_partition_rules(
341
        rule_data, ksdata_mock, storage_mock,
342
        rules, actual_mountpoints=["/"])
343
344
    # one mount option added, one mount point missing (mount options
345
    # cannot be added) --> one info, one error
346
    assert len(messages) == 2
347
    assert any(message.type == common.MESSAGE_TYPE_INFO for message in messages)
348
    assert any(message.type == common.MESSAGE_TYPE_FATAL for message in messages)
349
350
    # the info message should report mount options added to the existing
351
    # mount point, the error message shoud contain the missing mount point
352
    # and not the mount option
353
    for message in messages:
354
        if message.type == common.MESSAGE_TYPE_INFO:
355
            assert "/" in message.text
356
            assert "'noauto'" in message.text
357
        elif message.type == common.MESSAGE_TYPE_FATAL:
358
            assert "/tmp" in message.text
359
            assert "'nodev'" not in message.text
360
361
362
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
363
def test_evaluation_passwd_minlen_no_passwd(
364
        proxy_getter, rule_data, ksdata_mock, storage_mock):
365
    password_proxy_mock = mock.MagicMock()
366
    proxy_getter.return_value = password_proxy_mock
367
    password_proxy_mock.IsRootPasswordSet = False
368
    evaluation_passwd_minlen_no_passwd(rule_data, ksdata_mock, storage_mock, 8, (10, 11))
369
    evaluation_passwd_minlen_no_passwd(rule_data, ksdata_mock, storage_mock, 10, (8, 11))
370
    evaluation_passwd_minlen_no_passwd(rule_data, ksdata_mock, storage_mock, 11, (8, 10))
371
372
373
def evaluation_passwd_minlen_no_passwd(
374
        rule_data, ksdata_mock, storage_mock, min_password_length, check_against=tuple()):
375
    rule_data.new_rule("passwd --minlen={0}".format(min_password_length))
376
377
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
378
379
    # minimal password length required --> one warning
380
    assert len(messages) == 1
381
    assert messages[0].type == common.MESSAGE_TYPE_WARNING
382
383
    # warning has to mention the length
384
    assert str(min_password_length) in messages[0].text
385
386
    for not_wanted in check_against:
387
        assert str(not_wanted) not in messages[0].text
388
389
390 View Code Duplication
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
391
def test_evaluation_passwd_minlen_short_passwd(
392
        proxy_getter, rule_data, ksdata_mock, storage_mock):
393
    password_proxy_mock = mock.MagicMock()
394
    proxy_getter.return_value = password_proxy_mock
395
    password_proxy_mock.IsRootPasswordCrypted = False
396
    password_proxy_mock.RootPassword = "aaaa"
397
398
    rule_data.new_rule("passwd --minlen=8")
399
400
    messages = rule_data.eval_rules(ksdata_mock, storage_mock, report_only=False)
401
402
    # minimal password length greater than actual length --> one warning
403
    assert len(messages) == 1
404
    assert messages[0].type == common.MESSAGE_TYPE_FATAL
405
406
    # warning has to mention the length
407
    assert "8" in messages[0].text
408
409
    # warning should mention that something is wrong with the old password
410
    assert "is" in messages[0].text
411
412
    # doing changes --> password should not be cleared
413
    assert password_proxy_mock.RootPassword == "aaaa"
414
415
416 View Code Duplication
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
417
def test_evaluation_passwd_minlen_short_passwd_report_only(
418
        proxy_getter, rule_data, ksdata_mock, storage_mock):
419
    password_proxy_mock = mock.MagicMock()
420
    proxy_getter.return_value = password_proxy_mock
421
    password_proxy_mock.IsRootPasswordCrypted = False
422
    password_proxy_mock.RootPassword = "aaaa"
423
424
    rule_data.new_rule("passwd --minlen=8")
425
426
    messages = rule_data.eval_rules(ksdata_mock, storage_mock, report_only=True)
427
428
    # minimal password length greater than actual length --> one warning
429
    assert len(messages) == 1
430
    assert messages[0].type == common.MESSAGE_TYPE_FATAL
431
432
    # warning has to mention the length
433
    assert "8" in messages[0].text
434
435
    # warning should mention that something is wrong with the old password
436
    assert "is" in messages[0].text
437
438
    # doing changes --> password should not be cleared
439
    assert password_proxy_mock.RootPassword == "aaaa"
440
441
442
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
443
def test_evaluation_passwd_minlen_crypted_passwd(
444
        proxy_getter, rule_data, ksdata_mock, storage_mock):
445
    password_proxy_mock = mock.MagicMock()
446
    proxy_getter.return_value = password_proxy_mock
447
    password_proxy_mock.IsRootPasswordCrypted = True
448
    password_proxy_mock.RootPassword = "aaaa"
449
450
    rule_data.new_rule("passwd --minlen=8")
451
452
    messages = rule_data.eval_rules(ksdata_mock, storage_mock, report_only=False)
453
454
    # minimal password length greater than actual length --> one warning
455
    assert len(messages) == 1
456
    assert messages[0].type == common.MESSAGE_TYPE_WARNING
457
458
    # warning has to mention that the password cannot be checked
459
    assert "cannot check" in messages[0].text
460
461
462
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
463
def test_evaluation_passwd_minlen_good_passwd(proxy_getter, rule_data, ksdata_mock, storage_mock):
464
    password_proxy_mock = mock.MagicMock()
465
    proxy_getter.return_value = password_proxy_mock
466
    password_proxy_mock.IsRootPasswordCrypted = False
467
    password_proxy_mock.RootPassword = "aaaaaaaaaaaaaaaaa"
468
469
    rule_data.new_rule("passwd --minlen=8")
470
471
    messages = rule_data.eval_rules(ksdata_mock, storage_mock, report_only=False)
472
473
    # minimal password length less than actual length --> no warning
474
    assert not messages
475
476
477
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
478
def test_evaluation_passwd_minlen_report_only_not_ignored(
479
        proxy_getter, rule_data, ksdata_mock, storage_mock):
480
    password_proxy_mock = mock.MagicMock()
481
    proxy_getter.return_value = password_proxy_mock
482
    password_proxy_mock.IsRootPasswordCrypted = False
483
    password_proxy_mock.RootPassword = "aaaaaaaaaaaaaaaaa"
484
485
    rule_data.new_rule("passwd --minlen=8")
486
487
    messages = rule_data.eval_rules(ksdata_mock, storage_mock, report_only=False)
488
489
    # Mock pw_policy returned by anaconda.pwpolicy.get_policy()
490
    pw_policy_mock = mock.Mock()
491
    pw_policy_mock.minlen = 6
492
    pw_policy_mock.strict = False
493
    ksdata_mock.anaconda.pwpolicy.get_policy.return_value = pw_policy_mock
494
495
    # call eval_rules with report_only=False
496
    # should set password minimal length to 8
497
    messages = rule_data.eval_rules(ksdata_mock, storage_mock, report_only=False)
498
499
    # Password Policy changed --> no warnings
500
    assert not messages
501
    assert rule_data._passwd_rules._orig_minlen == 6
502
    assert not rule_data._passwd_rules._orig_strict
503
    assert pw_policy_mock.minlen == 8
504
    assert pw_policy_mock.strict
505
    assert rule_data._passwd_rules._minlen == 8
506
507
    # call of eval_rules with report_only=True
508
    # should not change anything
509
    messages = rule_data.eval_rules(ksdata_mock, storage_mock, report_only=True)
510
    # Password Policy stayed the same --> no warnings
511
    assert not messages
512
513
    assert rule_data._passwd_rules._orig_minlen == 6
514
    assert not rule_data._passwd_rules._orig_strict
515
    assert pw_policy_mock.minlen == 8
516
    assert pw_policy_mock.strict
517
    assert rule_data._passwd_rules._minlen == 8
518
519
520
def _occurences_not_seen_in_strings(seeked, strings):
521
    found = set(seeked)
522
    for string in strings:
523
        for might_have_seen in seeked:
524
            if might_have_seen in string:
525
                found.add(string)
526
                break
527
    return set(seeked).difference(found)
528
529
530
def _quoted_keywords_not_seen_in_messages(keywords, messages):
531
    return _occurences_not_seen_in_strings(
532
        {"'{}'".format(kw) for kw in keywords},
533
        [m.text for m in messages],
534
    )
535
536
537
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
538
def test_evaluation_package_rules(proxy_getter, rule_data, ksdata_mock, storage_mock):
539
    rule_data.new_rule("package --add=firewalld --remove=telnet --add=iptables --add=vim")
540
541
    ksdata_mock.packages.packageList = ["vim"]
542
    ksdata_mock.packages.excludedList = []
543
544
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
545
546
    # one info message for each (really) added/removed package
547
    assert len(messages) == 3
548
    assert all(message.type == common.MESSAGE_TYPE_INFO for message in messages)
549
550
    # all packages should appear in the messages
551
    not_seen = _quoted_keywords_not_seen_in_messages(
552
        {"firewalld", "telnet", "iptables"},
553
        messages,
554
    )
555
556
    assert not not_seen
557
    assert set(ksdata_mock.packages.packageList) == {"firewalld", "iptables", "vim"}
558
    assert set(ksdata_mock.packages.excludedList) == {"telnet"}
559
560
561
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
562
def test_evaluation_package_rules_report_only(proxy_getter, rule_data, ksdata_mock, storage_mock):
563
    rule_data.new_rule("package --add=firewalld --remove=telnet --add=iptables")
564
565
    ksdata_mock.packages.packageList = []
566
    ksdata_mock.packages.excludedList = []
567
568
    messages = rule_data.eval_rules(ksdata_mock, storage_mock, report_only=True)
569
570
    # one info message for each added/removed package
571
    assert len(messages) == 3
572
    assert all(message.type == common.MESSAGE_TYPE_INFO for message in messages)
573
574
    not_seen = _quoted_keywords_not_seen_in_messages(
575
        {"firewalld", "telnet", "iptables"},
576
        messages,
577
    )
578
579
    assert not not_seen
580
581
    # report_only --> no packages should be added or excluded
582
    assert not ksdata_mock.packages.packageList
583
    assert not ksdata_mock.packages.excludedList
584
585
586
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
587
def test_evaluation_bootloader_passwd_not_set(proxy_getter, rule_data, ksdata_mock, storage_mock):
588
    bootloader_proxy_mock = mock.MagicMock()
589
    proxy_getter.return_value = bootloader_proxy_mock
590
591
    bootloader_proxy_mock.password_is_set = False
592
593
    rule_data.new_rule("bootloader --passwd")
594
595
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
596
597
    # bootloader password not set --> one warning
598
    assert len(messages) == 1
599
    assert messages[0].type == common.MESSAGE_TYPE_WARNING
600
601
602
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
603
def test_evaluation_bootloader_passwd_set(proxy_getter, rule_data, ksdata_mock, storage_mock):
604
    bootloader_proxy_mock = mock.MagicMock()
605
    proxy_getter.return_value = bootloader_proxy_mock
606
607
    bootloader_proxy_mock.password_is_set = True
608
609
    rule_data.new_rule("bootloader --passwd")
610
611
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
612
613
    # bootloader password set --> no warnings
614
    assert messages == []
615
616
617
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
618
def test_evaluation_various_rules(proxy_getter, rule_data, ksdata_mock, storage_mock):
619
    for rule in ["part /tmp", "part /", "passwd --minlen=14",
620
                 "package --add=firewalld", ]:
621
        rule_data.new_rule(rule)
622
623
    storage_mock.mountpoints = dict()
624
    ksdata_mock.packages.packageList = []
625
    ksdata_mock.packages.excludedList = []
626
627
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
628
629
    # four rules, all fail --> four messages
630
    assert len(messages) == 4
631
632
633
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
634
def test_revert_mount_options_nonexistent(proxy_getter, rule_data, ksdata_mock, storage_mock):
635
    rule_data.new_rule("part /tmp --mountoptions=nodev")
636
    storage_mock.mountpoints = dict()
637
638
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
639
640
    # mount point doesn't exist -> one message, nothing done
641
    assert len(messages) == 1
642
    assert storage_mock.mountpoints == dict()
643
644
    # mount point doesn't exist -> shouldn't do anything
645
    rule_data.revert_changes(ksdata_mock, storage_mock)
646
    assert storage_mock.mountpoints == dict()
647
648
649
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
650
def test_revert_mount_options(proxy_getter, rule_data, ksdata_mock, storage_mock):
651
    rule_data.new_rule("part /tmp --mountoptions=nodev")
652
    storage_mock.mountpoints = dict()
653
    storage_mock.mountpoints["/tmp"] = mock.Mock()
654
    storage_mock.mountpoints["/tmp"].format.options = "defaults"
655
656
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
657
658
    # mount option added --> one message
659
    assert len(messages) == 1
660
661
    # "nodev" option should be added
662
    assert storage_mock.mountpoints["/tmp"].format.options, "defaults == nodev"
663
664
    rule_data.revert_changes(ksdata_mock, storage_mock)
665
666
    # should be reverted to the original value
667
    assert storage_mock.mountpoints["/tmp"].format.options == "defaults"
668
669
    # another cycle of the same #
670
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
671
672
    # mount option added --> one message
673
    assert len(messages) == 1
674
675
    # "nodev" option should be added
676
    assert storage_mock.mountpoints["/tmp"].format.options, "defaults == nodev"
677
678
    rule_data.revert_changes(ksdata_mock, storage_mock)
679
680
    # should be reverted to the original value
681
    assert storage_mock.mountpoints["/tmp"].format.options == "defaults"
682
683
684
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
685
def test_revert_password_policy_changes(proxy_getter, rule_data, ksdata_mock, storage_mock):
686
    password_proxy_mock = mock.MagicMock()
687
    proxy_getter.return_value = password_proxy_mock
688
    password_proxy_mock.IsRootPasswordCrypted = False
689
    password_proxy_mock.RootPassword = "aaaa"
690
691
    # FIXME: Add password policy changes to this test. It only checks
692
    # password length right now outside of policy changes.
693
    rule_data.new_rule("passwd --minlen=8")
694
695
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
696
697
    # password error --> one message
698
    assert len(messages) == 1
699
700
    rule_data.revert_changes(ksdata_mock, storage_mock)
701
702
    # with long enough password this time #
703
    password_proxy_mock.RootPassword = "aaaaaaaaaaaaa"
704
705
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
706
707
    # long enough password
708
    # entered --> no message
709
    assert messages == []
710
711
712
@mock.patch("pyanaconda.dbus.DBus.get_proxy")
713
def test_revert_package_rules(proxy_getter, rule_data, ksdata_mock, storage_mock):
714
    rule_data.new_rule("package --add=firewalld --remove=telnet --add=iptables --add=vim")
715
716
    ksdata_mock.packages.packageList = ["vim"]
717
    ksdata_mock.packages.excludedList = []
718
719
    # run twice --> nothing should be different in the second run
720
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
721
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
722
723
    # one info message for each added/removed package
724
    assert len(messages) == 3
725
726
    rule_data.revert_changes(ksdata_mock, storage_mock)
727
728
    # (only) added and excluded packages should have been removed from the
729
    # list
730
    assert ksdata_mock.packages.packageList == ["vim"]
731
    assert ksdata_mock.packages.excludedList == []
732
733
    # now do the same again #
734
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
735
736
    # one info message for each added/removed package
737
    assert len(messages) == 3
738
739
    rule_data.revert_changes(ksdata_mock, storage_mock)
740
741
    # (only) added and excluded packages should have been removed from the
742
    # list
743
    assert ksdata_mock.packages.packageList == ["vim"]
744
    assert ksdata_mock.packages.excludedList == []
745