commit: c074e090e057a6d4303b492493c8cd5e9a180107 Author: Sam James <sam <AT> gentoo <DOT> org> AuthorDate: Thu Feb 16 07:30:08 2023 +0000 Commit: Sam James <sam <AT> gentoo <DOT> org> CommitDate: Sat Feb 18 10:13:34 2023 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=c074e090
tests: news: use templates for mock news items This is some prep work to modernise the tests a bit by using dataclasses and idiomatic Python string/template substitution. The key point here is the changes facilitate testing with various combinations of fields, including multiple e.g. Display-If-Installed, which we couldn't do cleanly before. Bug: https://bugs.gentoo.org/889330 Signed-off-by: Sam James <sam <AT> gentoo.org> lib/portage/tests/news/test_NewsItem.py | 149 ++++++++++++++++++++++++-------- 1 file changed, 111 insertions(+), 38 deletions(-) diff --git a/lib/portage/tests/news/test_NewsItem.py b/lib/portage/tests/news/test_NewsItem.py index d5fbc10e0..fcfc06b13 100644 --- a/lib/portage/tests/news/test_NewsItem.py +++ b/lib/portage/tests/news/test_NewsItem.py @@ -8,45 +8,115 @@ from portage.news import NewsItem from portage.dbapi.virtual import testdbapi from tempfile import mkstemp +from dataclasses import dataclass +from string import Template +from typing import Optional + +import textwrap + # TODO(antarus) Make newsitem use a loader so we can load using a string instead of a tempfile +# TODO: port the real newsitem class to this? +@dataclass +class FakeNewsItem: + title: str + author: str + content_type: str + posted: str + revision: int + news_item_format: str + content: str + display_if_installed: Optional[list[str]] = None + display_if_profile: Optional[list[str]] = None + display_if_keyword: Optional[list[str]] = None + + item_template_header = Template( + textwrap.dedent( + """ + Title: ${title} + Author: ${author} + Content-Type: ${content_type} + Posted: ${posted} + Revision: ${revision} + News-Item-Format: ${news_item_format} + """ + ) + ) + + def __post_init__(self): + if not any( + [self.display_if_installed, self.display_if_profile, self.display_if_keyword] + ): + raise ValueError( + "At least one-of Display-If-Installed, Display-If-Profile, or Display-If-Arch must be set!" + ) + + def __str__(self) -> str: + item = self.item_template_header.substitute( + title=self.title, + author=self.author, + content_type=self.content_type, + posted=self.posted, + revision=self.revision, + news_item_format=self.news_item_format, + ) + + for package in self.display_if_installed: + item += f"Display-If-Installed: {package}\n" + + for profile in self.display_if_profile: + item += f"Display-If-Profile: {profile}\n" + + for keyword in self.display_if_keyword: + item += f"Display-If-Keyword: {keyword}\n" + + item += "\n" + item += f"{self.content}" + + return item + + class NewsItemTestCase(TestCase): """These tests suck: they use your running config instead of making their own""" - fakeItem = """ -Title: YourSQL Upgrades from 4.0 to 4.1 -Author: Ciaran McCreesh <[email protected]> -Content-Type: text/plain -Posted: 01-Nov-2005 -Revision: 1 -News-Item-Format: 1.0 -#Display-If-Installed: -#Display-If-Profile: -#Display-If-Arch: + # Default values for testing + placeholders = { + "title": "YourSQL Upgrades from 4.0 to 4.1", + "author": "Ciaran McCreesh <[email protected]>", + "content_type": "Content-Type: text/plain", + "posted": "01-Nov-2005", + "revision": 1, + "news_item_format": "1.0", + "display_if_installed": [], + "display_if_profile": [], + "display_if_keyword": [], + "content": textwrap.dedent( + """ + YourSQL databases created using YourSQL version 4.0 are incompatible + with YourSQL version 4.1 or later. There is no reliable way to + automate the database format conversion, so action from the system + administrator is required before an upgrade can take place. -YourSQL databases created using YourSQL version 4.0 are incompatible -with YourSQL version 4.1 or later. There is no reliable way to -automate the database format conversion, so action from the system -administrator is required before an upgrade can take place. + Please see the Gentoo YourSQL Upgrade Guide for instructions: -Please see the Gentoo YourSQL Upgrade Guide for instructions: + http://www.gentoo.org/doc/en/yoursql-upgrading.xml - http://www.gentoo.org/doc/en/yoursql-upgrading.xml + Also see the official YourSQL documentation: -Also see the official YourSQL documentation: + http://dev.yoursql.com/doc/refman/4.1/en/upgrading-from-4-0.html - http://dev.yoursql.com/doc/refman/4.1/en/upgrading-from-4-0.html + After upgrading, you should also recompile any packages which link + against YourSQL: -After upgrading, you should also recompile any packages which link -against YourSQL: + revdep-rebuild --library=libyoursqlclient.so.12 - revdep-rebuild --library=libyoursqlclient.so.12 + The revdep-rebuild tool is provided by app-portage/gentoolkit. + """ + ), + } -The revdep-rebuild tool is provided by app-portage/gentoolkit. -""" - - def setUp(self): + def setUp(self) -> None: self.profile = "/var/db/repos/gentoo/profiles/default-linux/x86/2007.0/" self.keywords = "x86" # Use fake/test dbapi to avoid slow tests @@ -55,12 +125,19 @@ The revdep-rebuild tool is provided by app-portage/gentoolkit. # Consumers only use ARCH, so avoid portage.settings by using a dict self.settings = {"ARCH": "x86"} + def _createNewsItem(self, *kwargs) -> FakeNewsItem: + # Use our placeholders unless overridden + news_args = self.placeholders.copy() + # Substitute in what we're given to allow for easily passing + # just custom values. + news_args.update(*kwargs) + + return FakeNewsItem(**news_args) + def testDisplayIfProfile(self): - tmpItem = self.fakeItem[:].replace( - "#Display-If-Profile:", f"Display-If-Profile: {self.profile}" - ) + tmpItem = self._createNewsItem({"display_if_profile": [self.profile]}) - item = self._processItem(tmpItem) + item = self._processItem(str(tmpItem)) try: self.assertTrue( item.isRelevant(self.vardb, self.settings, self.profile), @@ -70,12 +147,10 @@ The revdep-rebuild tool is provided by app-portage/gentoolkit. os.unlink(item.path) def testDisplayIfInstalled(self): - tmpItem = self.fakeItem[:].replace( - "#Display-If-Installed:", f"Display-If-Installed: {'sys-apps/portage'}" - ) + tmpItem = self._createNewsItem({"display_if_installed": ["sys-apps/portage"]}) try: - item = self._processItem(tmpItem) + item = self._processItem(str(tmpItem)) self.assertTrue( item.isRelevant(self.vardb, self.settings, self.profile), msg=f"Expected {tmpItem} to be relevant, but it was not!", @@ -84,12 +159,10 @@ The revdep-rebuild tool is provided by app-portage/gentoolkit. os.unlink(item.path) def testDisplayIfKeyword(self): - tmpItem = self.fakeItem[:].replace( - "#Display-If-Keyword:", f"Display-If-Keyword: {self.keywords}" - ) + tmpItem = self._createNewsItem({"display_if_keyword": [self.keywords]}) try: - item = self._processItem(tmpItem) + item = self._processItem(str(tmpItem)) self.assertTrue( item.isRelevant(self.vardb, self.settings, self.profile), msg=f"Expected {tmpItem} to be relevant, but it was not!", @@ -97,7 +170,7 @@ The revdep-rebuild tool is provided by app-portage/gentoolkit. finally: os.unlink(item.path) - def _processItem(self, item): + def _processItem(self, item) -> NewsItem: filename = None fd, filename = mkstemp() f = os.fdopen(fd, "w")
