blob: be9076c5aae8655bc2c87ae761651a3eda2f70ea [file] [log] [blame]
Mike Frysingerfcdd9422022-12-28 10:59:06 -05001# Copyright 2022 The ChromiumOS Authors
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Test the cros_losetup module."""
6
7import json
Ram Chandrasekar65621a22023-04-11 17:18:12 -06008from pathlib import Path
Mike Frysingerfcdd9422022-12-28 10:59:06 -05009
10import pytest
11
Ram Chandrasekar65621a22023-04-11 17:18:12 -060012from chromite.lib import constants
13from chromite.lib import cros_build_lib
14from chromite.lib import cros_test_lib
Mike Frysingerfcdd9422022-12-28 10:59:06 -050015from chromite.lib import image_lib
16from chromite.lib import osutils
17from chromite.scripts import cros_losetup
18
19
20@pytest.fixture(autouse=True)
21def is_root_fixture(monkeypatch):
22 """We don't want the code re-execing itself using sudo."""
23 monkeypatch.setattr(osutils, "IsRootUser", lambda: True)
24
25
26@pytest.fixture(autouse=True)
27def stub_image_lib(monkeypatch):
28 """Make sure these APIs aren't used by default."""
29
30 def fail(path):
31 raise RuntimeError("test is missing a mock")
32
33 monkeypatch.setattr(image_lib.LoopbackPartitions, "detach_loopback", fail)
34 monkeypatch.setattr(image_lib.LoopbackPartitions, "attach_image", fail)
35
36
Ram Chandrasekar65621a22023-04-11 17:18:12 -060037@pytest.fixture(autouse=True)
38def path_write_text_fixture(monkeypatch):
39 """Make sure we dont write the udev rule during test."""
40 monkeypatch.setattr(cros_build_lib, "IsInsideChroot", lambda: True)
41
42
Mike Frysingerfcdd9422022-12-28 10:59:06 -050043def test_parser():
44 """Basic tests for the parser interface."""
45 parser = cros_losetup.get_parser()
46
47 # Missing subcommand.
48 with pytest.raises(SystemExit):
49 parser.parse_args([])
50
51 # Unknown subcommand.
52 with pytest.raises(SystemExit):
53 parser.parse_args(["asdfadsf"])
54
55 # Missing path.
56 with pytest.raises(SystemExit):
57 parser.parse_args(["attach"])
58 with pytest.raises(SystemExit):
59 parser.parse_args(["detach"])
60
61 # Valid commands.
62 parser.parse_args(["attach", "disk.bin"])
63 parser.parse_args(["detach", "/dev/loop0"])
64
65
66def test_attach(monkeypatch, capsys):
67 """Verify attaching runs lower APIs."""
68 monkeypatch.setattr(
69 image_lib.LoopbackPartitions, "attach_image", lambda x: "/dev/loop0"
70 )
71 assert cros_losetup.main(["attach", "disk.bin"]) == 0
72
73 # Stdout should be JSON.
74 captured = capsys.readouterr()
75 data = json.loads(captured.out)
76 assert "path" in data
77 assert data["path"] == "/dev/loop0"
78
79
80def test_detach_success(monkeypatch):
81 """Verify detaching runs lower APIs."""
82 monkeypatch.setattr(
83 image_lib.LoopbackPartitions, "detach_loopback", lambda x: True
84 )
85 assert cros_losetup.main(["detach", "/dev/loop0"]) == 0
86
87
88def test_detach_failure(monkeypatch):
89 """Verify detaching runs lower APIs."""
90 monkeypatch.setattr(
91 image_lib.LoopbackPartitions, "detach_loopback", lambda x: False
92 )
93 assert cros_losetup.main(["detach", "/dev/loop0"]) == 1
Ram Chandrasekar65621a22023-04-11 17:18:12 -060094
95
96def test_create_udev_rule(monkeypatch):
97 """Test if the udev rule is created with the chromite source directory."""
98 with osutils.TempDir() as tempdir:
99 _cros_losetup_tmpfile = Path(tempdir) / "udev.rules"
100 monkeypatch.setattr(
101 cros_losetup, "_UDEV_RULE_FILE", _cros_losetup_tmpfile
102 )
103 with cros_test_lib.RunCommandMock() as rc:
104 rc.SetDefaultCmdResult()
105 # Test when we are inside chroot.
106 # pylint: disable-msg=protected-access
107 cros_losetup._create_udev_loopdev_ignore_rule()
108 assert not _cros_losetup_tmpfile.exists()
109
110 # Test when we are outside chroot.
111 monkeypatch.setattr(cros_build_lib, "IsInsideChroot", lambda: False)
112 cros_losetup._create_udev_loopdev_ignore_rule()
113 assert _cros_losetup_tmpfile.read_text(encoding="utf-8") == (
114 cros_losetup._UDEV_RULE_TEMPLATE % constants.SOURCE_ROOT
115 )
116 rc.assertCommandContains(["udevadm", "control", "--reload-rules"])
117
118 # Test when the file already exists, we dont call udev reload-rules.
119 call_count = rc.call_count
120 cros_losetup._create_udev_loopdev_ignore_rule()
121 assert _cros_losetup_tmpfile.read_text(encoding="utf-8") == (
122 cros_losetup._UDEV_RULE_TEMPLATE % constants.SOURCE_ROOT
123 )
124 assert rc.call_count == call_count