|
| 1 | +# pylint: disable=missing-module-docstring |
| 2 | +import datetime |
| 3 | +import gzip |
1 | 4 | import io |
2 | | -import os.path |
3 | | -from unittest.mock import patch, mock_open |
| 5 | +import unittest |
4 | 6 |
|
5 | | -from lzreposync import Handler, RPMRepo |
| 7 | +from lzreposync.filelists_parser import FilelistsParser |
| 8 | +from lzreposync.primary_parser import ( |
| 9 | + PrimaryParser, |
| 10 | + complex_attrs, |
| 11 | + map_dependency_attribute, |
| 12 | +) |
| 13 | +from lzreposync.rpm_metadata_parser import MetadataParser |
6 | 14 |
|
7 | 15 |
|
8 | 16 | def test_download_and_parse_metadata(): |
9 | | - test_hash = "00c99a7e67dac325f1cbeeedddea3e4001a8f803c9bf43d9f50b5f1c756b0887" |
10 | | - test_name = "Leap15" |
11 | | - test_cache_dir = ".cache" |
12 | | - test_repo = "https://download.opensuse.org/update/leap/15.5/oss/repodata/" |
13 | | - cache_file = os.path.join("{}/{}".format(test_cache_dir, test_name), test_name + ".hash") |
14 | | - test_rpm_handler = Handler() |
| 17 | + """TODO""" |
15 | 18 |
|
16 | | - with patch("builtins.open", mock_open()) as mocked_file: |
17 | | - rpm_repo = RPMRepo(test_name, test_cache_dir, |
18 | | - test_repo, |
19 | | - test_rpm_handler) |
20 | | - rpm_repo.get_packages_metadata() |
21 | 19 |
|
22 | | - mocked_file.assert_called_once_with(cache_file, 'w') |
23 | | - mocked_file().write.assert_called_once_with(test_hash) |
| 20 | +def test_verify_signature(): |
| 21 | + """TODO""" |
24 | 22 |
|
25 | 23 |
|
26 | | -def test_parse_primary_missing_element_attributes(): |
27 | | - """ |
28 | | - Testing the parsing with a primary.xml file of 2 packages, one of which have missing element attributes: |
29 | | - 'epoch' and the 'ver' of the second package are missing. |
30 | | - The current parser's behaviour is to ignore the missing attribute, and continue parsing |
31 | | - """ |
32 | | - test_primary_path = "primary_test_missing_element_attributes.xml.gz" |
33 | | - test_cache_dir = ".cache" |
34 | | - handler = Handler() |
| 24 | +class LazyRepoSyncTest(unittest.TestCase): |
35 | 25 |
|
36 | | - with open(test_primary_path, "rb") as primary_gz: |
37 | | - file_obj = io.BytesIO(primary_gz.read()) |
| 26 | + def test_parse_primary(self): |
| 27 | + """ |
| 28 | + Test the parsing functionality for rpm's primary.xml metadata file |
| 29 | + """ |
38 | 30 |
|
39 | | - rpm_repo = RPMRepo(None, test_cache_dir, None, handler) |
40 | | - parsed_packages_count = rpm_repo.parse_metadata_file(file_obj) |
| 31 | + # Prepare test data: valid rpm package metadata in primary.xml |
| 32 | + primary_xml = """<?xml version="1.0" encoding="UTF-8"?> |
| 33 | + <metadata xmlns="http://linux.duke.edu/metadata/common" xmlns:rpm="http://linux.duke.edu/metadata/rpm" packages="1"> |
| 34 | + <package type="rpm"> |
| 35 | + <name>gstreamer-plugins-bad</name> |
| 36 | + <arch>aarch64</arch> |
| 37 | + <version epoch="0" ver="1.22.0" rel="lp155.3.4.1"/> |
| 38 | + <checksum type="sha256" pkgid="YES">5f32047b55c0ca2dcc00a00270cd0b10df4df40c6cd9355eeff9b6aa0997657b</checksum> |
| 39 | + <summary>GStreamer Streaming-Media Framework Plug-Ins</summary> |
| 40 | + <description>GStreamer is a streaming media framework based on graphs of filters |
| 41 | + that operate on media data... |
| 42 | + </description> |
| 43 | + <packager>http://bugs.opensuse.org</packager> |
| 44 | + <url>https://gstreamer.freedesktop.org</url> |
| 45 | + <time file="1700989109" build="1696852591"/> |
| 46 | + <size package="2197472" installed="11946385" archive="11965968"/> |
| 47 | + <location href="aarch64/gstreamer-plugins-bad-1.22.0-lp155.3.4.1.aarch64.rpm"/> |
| 48 | + <format> |
| 49 | + <rpm:license>LGPL-2.1-or-later</rpm:license> |
| 50 | + <rpm:vendor>openSUSE</rpm:vendor> |
| 51 | + <rpm:group>Productivity/Multimedia/Other</rpm:group> |
| 52 | + <rpm:buildhost>armbuild26</rpm:buildhost> |
| 53 | + <rpm:sourcerpm>gstreamer-plugins-bad-1.22.0-lp155.3.4.1.src.rpm</rpm:sourcerpm> |
| 54 | + <rpm:header-range start="6200" end="149568"/> |
| 55 | + <rpm:provides> |
| 56 | + <rpm:entry name="gst-plugins-bad" flags="EQ" epoch="0" ver="1.22.0"/> |
| 57 | + <rpm:entry name="gstreamer-plugins-bad" flags="EQ" epoch="0" ver="1.22.0" rel="lp155.3.4.1"/> |
| 58 | + </rpm:provides> |
| 59 | + <rpm:requires> |
| 60 | + <rpm:entry name="glib2-tools" pre="1"/> |
| 61 | + <rpm:entry name="glib2-tools"/> |
| 62 | + </rpm:requires> |
| 63 | + <rpm:obsoletes> |
| 64 | + <rpm:entry name="libgstvdpau" flags="LT" epoch="0" ver="1.18.0"/> |
| 65 | + </rpm:obsoletes> |
| 66 | + <rpm:enhances> |
| 67 | + <rpm:entry name="gstreamer"/> |
| 68 | + </rpm:enhances> |
| 69 | + </format> |
| 70 | + </package> |
| 71 | + </metadata> |
| 72 | + """ |
| 73 | + package_data = { |
| 74 | + "package_size": "2197472", |
| 75 | + "checksum": "5f32047b55c0ca2dcc00a00270cd0b10df4df40c6cd9355eeff9b6aa0997657b", |
| 76 | + "checksum_type": "sha256", |
| 77 | + "header_start": "6200", |
| 78 | + "header_end": "149568", |
| 79 | + "remote_path": "aarch64/gstreamer-plugins-bad-1.22.0-lp155.3.4.1.aarch64.rpm", |
| 80 | + } |
| 81 | + package_header_data = { |
| 82 | + "name": "gstreamer-plugins-bad", |
| 83 | + "arch": "aarch64", |
| 84 | + "version": "1.22.0", |
| 85 | + "release": "lp155.3.4.1", |
| 86 | + "epoch": "0", |
| 87 | + "summary": "GStreamer Streaming-Media Framework Plug-Ins", |
| 88 | + "description": "GStreamer is a streaming media framework based on graphs of filters\n\ |
| 89 | + that operate on media data...", |
| 90 | + "packager": "http://bugs.opensuse.org", |
| 91 | + "url": "https://gstreamer.freedesktop.org", |
| 92 | + "buildtime": datetime.datetime.fromtimestamp(float(1696852591)), |
| 93 | + "installed_size": "11946385", |
| 94 | + "archivesize": int(11965968), |
| 95 | + "license": "LGPL-2.1-or-later", |
| 96 | + "vendor": "openSUSE", |
| 97 | + "group": "Productivity/Multimedia/Other", |
| 98 | + "buildhost": "armbuild26", |
| 99 | + "sourcerpm": "gstreamer-plugins-bad-1.22.0-lp155.3.4.1.src.rpm", |
| 100 | + } |
41 | 101 |
|
42 | | - assert parsed_packages_count == 2 |
| 102 | + compressed_primary = gzip.compress(bytes(primary_xml, "utf-8")) |
| 103 | + primary_xml_file_obj = io.BytesIO(compressed_primary) |
43 | 104 |
|
| 105 | + # Parse the test package md |
| 106 | + primary_parser = PrimaryParser(primary_xml_file_obj) |
| 107 | + parsed_packages = list(primary_parser.parse_primary()) |
44 | 108 |
|
45 | | -def test_verify_signature(): |
46 | | - """ |
47 | | - Note: this test case assumes that the repomd.xml file hasn't been altered, if so it will fail |
48 | | - """ |
49 | | - test_repo = "https://download.opensuse.org/update/leap/15.5/oss/repodata/" |
50 | | - test_cache_dir = ".cache" |
| 109 | + # Assertions |
| 110 | + test_package = parsed_packages[0] |
| 111 | + test_package_elements = test_package.keys() |
| 112 | + test_package_hdr_elements = test_package["header"].keys() |
| 113 | + self.assertEqual(len(parsed_packages), 1) |
| 114 | + |
| 115 | + # Check package data |
| 116 | + for elt, val in package_data.items(): |
| 117 | + self.assertTrue(elt in test_package_elements) |
| 118 | + self.assertEqual(test_package[elt], val) |
| 119 | + |
| 120 | + # Check package's header data |
| 121 | + for elt, val in package_header_data.items(): |
| 122 | + self.assertTrue(elt in test_package_hdr_elements) |
| 123 | + self.assertEqual(test_package["header"][elt], val) |
| 124 | + |
| 125 | + # Check package's capabilities |
| 126 | + for dep in complex_attrs: |
| 127 | + for attribute in ( |
| 128 | + ("name", "version", "flags") |
| 129 | + if dep != "changelog" |
| 130 | + else ("name", "text", "time") |
| 131 | + ): |
| 132 | + dep_mapped_name = map_dependency_attribute(dep, attribute) |
| 133 | + if dep == "provides" or dep == "requires": |
| 134 | + self.assertEqual(len(test_package["header"][dep_mapped_name]), 2) |
| 135 | + continue |
| 136 | + if dep == "obsoletes" or dep == "enhances": |
| 137 | + self.assertEqual(len(test_package["header"][dep_mapped_name]), 1) |
| 138 | + continue |
| 139 | + |
| 140 | + # Else: non-existing attributes |
| 141 | + self.assertEqual(len(test_package["header"][dep_mapped_name]), 0) |
| 142 | + |
| 143 | + def test_parse_file_lists(self): |
| 144 | + """ |
| 145 | + Test the parsing functionality for rpm's filelists.xml metadata file |
| 146 | + """ |
| 147 | + |
| 148 | + file_lists_xml = """<?xml version="1.0" encoding="UTF-8"?> |
| 149 | + <filelists xmlns="http://linux.duke.edu/metadata/filelists" packages="2"> |
| 150 | + <package pkgid="5f32047b55c0ca2dcc00a00270cd0b10df4df40c6cd9355eeff9b6aa0997657b" name="gstreamer-plugins-bad" arch="aarch64"> |
| 151 | + <version epoch="0" ver="1.1.0" rel="lp155.3.4.1"/> |
| 152 | + <file>/usr/lib64/gstreamer-1.0/libgstaiff.so</file> |
| 153 | + <file>/usr/lib64/gstreamer-1.0/libgstaccurip.so</file> |
| 154 | + <file>/usr/lib64/gstreamer-1.0/libgstadpcmdec.so</file> |
| 155 | + <file>/usr/lib64/gstreamer-1.0/libgstadpcmenc.so</file> |
| 156 | + </package> |
| 157 | + <package pkgid="5aac91b3ec4b358b22fe50cf0a23d6ea6139ca2f1909f99b6c3b5734ca12530f" name="gstreamer-plugins-bad" arch="ppc64le"> |
| 158 | + <version epoch="0" ver="2.2.0" rel="lp155.3.4.1"/> |
| 159 | + <file>/usr/lib64/gstreamer-1.0/libgstaccurip.so</file> |
| 160 | + <file>/usr/lib64/gstreamer-1.0/libgstadpcmdec.so</file> |
| 161 | + <file>/usr/lib64/gstreamer-1.0/libgstadpcmenc.so</file> |
| 162 | + </package> |
| 163 | + </filelists>""" |
| 164 | + compressed_file_lists = gzip.compress(bytes(file_lists_xml, "utf-8")) |
| 165 | + file_lists_xml_obj_file = io.BytesIO(compressed_file_lists) |
| 166 | + |
| 167 | + file_lists_parser = FilelistsParser(file_lists_xml_obj_file) |
| 168 | + file_lists_parser.parse_filelists() |
| 169 | + |
| 170 | + package_files_5f32 = file_lists_parser.get_package_filelist( |
| 171 | + "5f32047b55c0ca2dcc00a00270cd0b10df4df40c6cd9355eeff9b6aa0997657b" |
| 172 | + ) |
| 173 | + package_files_5aac = file_lists_parser.get_package_filelist( |
| 174 | + "5aac91b3ec4b358b22fe50cf0a23d6ea6139ca2f1909f99b6c3b5734ca12530f" |
| 175 | + ) |
| 176 | + |
| 177 | + # Delete the cached files |
| 178 | + file_lists_parser.clear_cache() |
| 179 | + |
| 180 | + # First package |
| 181 | + self.assertEqual( |
| 182 | + package_files_5f32["pkgid"], |
| 183 | + "5f32047b55c0ca2dcc00a00270cd0b10df4df40c6cd9355eeff9b6aa0997657b", |
| 184 | + ) |
| 185 | + self.assertEqual(len(package_files_5f32["files"]), 4) |
| 186 | + self.assertEqual(package_files_5f32["version"], "1.1.0") |
| 187 | + self.assertEqual(package_files_5f32["epoch"], "0") |
| 188 | + self.assertEqual(package_files_5f32["release"], "lp155.3.4.1") |
| 189 | + self.assertEqual( |
| 190 | + package_files_5f32["files"][0], "/usr/lib64/gstreamer-1.0/libgstaiff.so" |
| 191 | + ) |
| 192 | + |
| 193 | + # Second package |
| 194 | + self.assertEqual( |
| 195 | + package_files_5aac["pkgid"], |
| 196 | + "5aac91b3ec4b358b22fe50cf0a23d6ea6139ca2f1909f99b6c3b5734ca12530f", |
| 197 | + ) |
| 198 | + self.assertEqual(len(package_files_5aac["files"]), 3) |
| 199 | + self.assertEqual(package_files_5aac["version"], "2.2.0") |
| 200 | + self.assertEqual(package_files_5aac["epoch"], "0") |
| 201 | + self.assertEqual(package_files_5aac["release"], "lp155.3.4.1") |
| 202 | + self.assertEqual( |
| 203 | + package_files_5aac["files"][0], "/usr/lib64/gstreamer-1.0/libgstaccurip.so" |
| 204 | + ) |
| 205 | + |
| 206 | + def test_parse_metadata(self): |
| 207 | + """TODO: both valid primary and filelists |
| 208 | + Create header with full information |
| 209 | + """ |
| 210 | + |
| 211 | + # primary & filelists test file |
| 212 | + primary_parser = PrimaryParser("test-files/primary-sample-2.xml.gz") |
| 213 | + file_lists_parser = FilelistsParser("test-files/filelists-sample-2.xml.gz") |
| 214 | + |
| 215 | + rpm_metadata_parser = MetadataParser(primary_parser, file_lists_parser) |
| 216 | + package_gen = rpm_metadata_parser.parse_packages_metadata() |
| 217 | + |
| 218 | + package_gen = rpm_metadata_parser.parse_packages_metadata() |
| 219 | + package1 = next(package_gen) |
| 220 | + package2 = next(package_gen) |
| 221 | + |
| 222 | + # First pacakge |
| 223 | + pkgid = package1["checksum"] |
| 224 | + self.assertEqual( |
| 225 | + pkgid, "5f32047b55c0ca2dcc00a00270cd0b10df4df40c6cd9355eeff9b6aa0997657b" |
| 226 | + ) |
| 227 | + self.assertEqual(package1["header"]["name"], "gstreamer-plugins-bad") |
| 228 | + # files |
| 229 | + self.assertEqual(len(package1["header"]["filenames"]), 8) |
| 230 | + self.assertEqual( |
| 231 | + package1["header"]["filenames"][0], |
| 232 | + file_lists_parser.get_package_filelist(pkgid)["files"][0], |
| 233 | + ) |
| 234 | + # capabilities |
| 235 | + self.assertEqual(len(package1["header"]["provides"]), 5) |
| 236 | + self.assertEqual(len(package1["header"]["provideversion"]), 5) |
| 237 | + self.assertEqual(len(package1["header"]["provideflags"]), 5) |
| 238 | + |
| 239 | + self.assertEqual(len(package1["header"]["requirename"]), 7) |
| 240 | + self.assertEqual(len(package1["header"]["requireversion"]), 7) |
| 241 | + self.assertEqual(len(package1["header"]["requireflags"]), 7) |
| 242 | + |
| 243 | + self.assertEqual(len(package1["header"][5055]), 1) # 'enhancesname' |
| 244 | + self.assertEqual(len(package1["header"][5056]), 1) # 'enhancesversion' |
| 245 | + self.assertEqual(len(package1["header"][5057]), 1) # 'enhancesflags' |
| 246 | + |
| 247 | + self.assertEqual(len(package1["header"]["obsoletename"]), 1) # 'enhancesflags' |
| 248 | + self.assertEqual( |
| 249 | + len(package1["header"]["obsoleteversion"]), 1 |
| 250 | + ) # 'enhancesflags' |
| 251 | + self.assertEqual(len(package1["header"]["obsoleteflags"]), 1) # 'enhancesflags' |
| 252 | + |
| 253 | + # Second pacakge |
| 254 | + pkgid2 = package2["checksum"] |
| 255 | + self.assertEqual( |
| 256 | + pkgid2, "5aac91b3ec4b358b22fe50cf0a23d6ea6139ca2f1909f99b6c3b5734ca12530f" |
| 257 | + ) |
| 258 | + |
| 259 | + file_lists_parser.clear_cache() |
| 260 | + |
| 261 | + def test_arch_filter_primary(self): |
| 262 | + """ |
| 263 | + Test the primary.xml parsing functionality with the 'arch' filter |
| 264 | + """ |
| 265 | + |
| 266 | + primary_gz_test = "test-files/primary-sample-10.xml.gz" |
| 267 | + archs = { |
| 268 | + "x86_64": 1, |
| 269 | + "aarch64": 2, |
| 270 | + "ppc64le": 4, |
| 271 | + "noarch": 3, |
| 272 | + "(x86_64|aarch64)": 3, |
| 273 | + "(ppc64le|noarch)": 7, |
| 274 | + ".*": 10, |
| 275 | + } |
| 276 | + |
| 277 | + for arch, count in archs.items(): |
| 278 | + primary_parser = PrimaryParser(primary_gz_test, arch_filter=arch) |
| 279 | + parsed_packages = list(primary_parser.parse_primary()) |
| 280 | + self.assertEqual(len(parsed_packages), count) |
| 281 | + |
| 282 | + def test_arch_filter_file_lists(self): |
| 283 | + """ |
| 284 | + Test the filelists.xml parsing functionality with the 'arch' filter |
| 285 | + """ |
| 286 | + file_lists_gz_test = "test-files/filelists-sample-10.xml.gz" |
| 287 | + archs = { |
| 288 | + "aarch64": 2, |
| 289 | + "ppc64le": 2, |
| 290 | + "src": 2, |
| 291 | + "x86_64": 2, |
| 292 | + "s390x": 2, |
| 293 | + "(ppc64le|s390x|src)": 6, |
| 294 | + ".*": 10, |
| 295 | + } |
| 296 | + |
| 297 | + for arch, count in archs.items(): |
| 298 | + file_lists_parser = FilelistsParser(file_lists_gz_test, arch_filter=arch) |
| 299 | + file_lists_parser.parse_filelists() |
| 300 | + self.assertEqual(file_lists_parser.num_parsed_packages, count) |
| 301 | + |
| 302 | + file_lists_parser.clear_cache() |
| 303 | + |
| 304 | + def test_arch_filter_packages(self): |
| 305 | + """ |
| 306 | + Test the parse metadata functionality (both primary and filelists) with the 'arch' filter |
| 307 | + """ |
| 308 | + |
| 309 | + def test_insert_batch_into_db(self): |
| 310 | + """ |
| 311 | + TODO: create a sample batch of package and verify it has been inserted correctly |
| 312 | + """ |
51 | 313 |
|
52 | | - rpm_repo = RPMRepo(None, test_cache_dir, test_repo, None) |
53 | 314 |
|
54 | | - assert rpm_repo.verify_signature() |
| 315 | +if __name__ == "__main__": |
| 316 | + unittest.main() |
0 commit comments