Skip to content

Commit d12d51a

Browse files
committed
Add unit tests for rpm metadata parsers
1 parent 98b4b47 commit d12d51a

File tree

5 files changed

+300
-38
lines changed

5 files changed

+300
-38
lines changed
782 Bytes
Binary file not shown.
453 Bytes
Binary file not shown.
932 Bytes
Binary file not shown.
1.19 KB
Binary file not shown.
Lines changed: 300 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,316 @@
1+
# pylint: disable=missing-module-docstring
2+
import datetime
3+
import gzip
14
import io
2-
import os.path
3-
from unittest.mock import patch, mock_open
5+
import unittest
46

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
614

715

816
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"""
1518

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()
2119

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"""
2422

2523

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):
3525

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+
"""
3830

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+
}
41101

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)
43104

105+
# Parse the test package md
106+
primary_parser = PrimaryParser(primary_xml_file_obj)
107+
parsed_packages = list(primary_parser.parse_primary())
44108

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+
"""
51313

52-
rpm_repo = RPMRepo(None, test_cache_dir, test_repo, None)
53314

54-
assert rpm_repo.verify_signature()
315+
if __name__ == "__main__":
316+
unittest.main()

0 commit comments

Comments
 (0)