From 37adfb0150cd405facb9ab970d230664cf5f9aee Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Fri, 7 Jun 2019 20:55:11 -0400 Subject: [PATCH] urlfetcher: Add http and ftp unit test mocking --- .../compare/virt-install-fake-ftp.xml | 87 +++++++++++++++++++ .../compare/virt-install-fake-http.xml | 87 +++++++++++++++++++ tests/clitest.py | 2 + tests/test_urls.py | 5 +- virtinst/osdict.py | 11 +++ virtinst/urlfetcher.py | 85 ++++++++++++++++-- 6 files changed, 270 insertions(+), 7 deletions(-) create mode 100644 tests/cli-test-xml/compare/virt-install-fake-ftp.xml create mode 100644 tests/cli-test-xml/compare/virt-install-fake-http.xml diff --git a/tests/cli-test-xml/compare/virt-install-fake-ftp.xml b/tests/cli-test-xml/compare/virt-install-fake-ftp.xml new file mode 100644 index 000000000..ab9a888af --- /dev/null +++ b/tests/cli-test-xml/compare/virt-install-fake-ftp.xml @@ -0,0 +1,87 @@ + + foobar + 00000000-1111-2222-3333-444444444444 + + + + + + 65536 + 65536 + 2 + + hvm + /tmp/virtinst-vmlinuz. + /tmp/virtinst-initrd.img. + method=ftp://example.com + + + + + + destroy + + + + + + /usr/bin/test-hv + + + + + + + + + + + + + + + + + + + foobar + 00000000-1111-2222-3333-444444444444 + + + + + + 65536 + 65536 + 2 + + hvm + + + + + + + + + + + + /usr/bin/test-hv + + + + + + + + + + + + + + + + + diff --git a/tests/cli-test-xml/compare/virt-install-fake-http.xml b/tests/cli-test-xml/compare/virt-install-fake-http.xml new file mode 100644 index 000000000..08a11b18c --- /dev/null +++ b/tests/cli-test-xml/compare/virt-install-fake-http.xml @@ -0,0 +1,87 @@ + + foobar + 00000000-1111-2222-3333-444444444444 + + + + + + 65536 + 65536 + 2 + + hvm + /tmp/virtinst-vmlinuz. + /tmp/virtinst-initrd.img. + method=https://foobar.com + + + + + + destroy + + + + + + /usr/bin/test-hv + + + + + + + + + + + + + + + + + + + foobar + 00000000-1111-2222-3333-444444444444 + + + + + + 65536 + 65536 + 2 + + hvm + + + + + + + + + + + + /usr/bin/test-hv + + + + + + + + + + + + + + + + + diff --git a/tests/clitest.py b/tests/clitest.py index 6b3c4dc0d..acf731b90 100644 --- a/tests/clitest.py +++ b/tests/clitest.py @@ -782,6 +782,8 @@ c.add_valid("--cdrom %(EXISTIMG2)s --os-variant win2k3 --wait 0 --print-step 2") c.add_valid("--pxe --autostart") # --autostart flag c.add_compare("--cdrom http://example.com/path/to/some.iso", "cdrom-url") c.add_compare("--pxe --print-step all", "simple-pxe") # Diskless PXE install +c.add_compare("--location ftp://example.com", "fake-ftp") # fake ftp:// install using urlfetcher.py mocking +c.add_compare("--location https://foobar.com", "fake-http") # fake https:// install using urlfetcher.py mocking c.add_invalid("--pxe --virt-type bogus") # Bogus virt-type c.add_invalid("--pxe --arch bogus") # Bogus arch c.add_invalid("--livecd") # LiveCD with no media diff --git a/tests/test_urls.py b/tests/test_urls.py index fbc496375..4358bfa43 100644 --- a/tests/test_urls.py +++ b/tests/test_urls.py @@ -16,6 +16,9 @@ import virtinst.progress from virtinst import Installer from virtinst import Guest +# These are all functional tests +os.environ.pop("VIRTINST_TEST_SUITE", None) + class _URLTestData(object): """ @@ -182,8 +185,6 @@ def _testURL(testdata): def _testURLWrapper(testdata): - os.environ.pop("VIRTINST_TEST_SUITE", None) - sys.stdout.write("\nTesting %-25s " % testdata.name) sys.stdout.flush() diff --git a/virtinst/osdict.py b/virtinst/osdict.py index 1e330972e..d94d9370c 100644 --- a/virtinst/osdict.py +++ b/virtinst/osdict.py @@ -8,11 +8,16 @@ import datetime import logging +import os import re from gi.repository import Libosinfo +def _in_testsuite(): + return "VIRTINST_TEST_SUITE" in os.environ + + ################### # Sorting helpers # ################### @@ -234,6 +239,12 @@ class _OSDB(object): def guess_os_by_tree(self, location): if location.startswith("/"): location = "file://" + location + + if _in_testsuite() and not location.startswith("file:"): + # We have mock network tests, but we don't want to pass the + # fake URL to libosinfo because it slows down the testcase + return None + try: tree = Libosinfo.Tree.create_from_location(location, None) except Exception as e: diff --git a/virtinst/urlfetcher.py b/virtinst/urlfetcher.py index 25afa7620..67207c4ce 100644 --- a/virtinst/urlfetcher.py +++ b/virtinst/urlfetcher.py @@ -3,6 +3,8 @@ # # This work is licensed under the GNU GPLv2 or later. # See the COPYING file in the top-level directory. +# +# Backends for the various URL types we support (http, https, ftp, local) import ftplib import io @@ -15,9 +17,74 @@ import urllib import requests -########################################################################### -# Backends for the various URL types we support (http, https, ftp, local) # -########################################################################### +############################## +# Mocking for the test suite # +############################## + +def _in_testsuite(): + return "VIRTINST_TEST_SUITE" in os.environ + + +def _make_mock_url(url, filesyntax): + if url.endswith("treeinfo"): + # If the url is requesting treeinfo, give a fake treeinfo from + # our testsuite data + fn = ("%s/../tests/cli-test-xml/fakerhel6tree/.treeinfo" % + os.path.abspath(os.path.dirname(__file__))) + abspath = os.path.abspath(fn) + else: + # Otherwise just copy this file + abspath = os.path.abspath(__file__) + + if filesyntax: + return "file://" + abspath + return abspath + + +class _MockRequestsResponse: + def __init__(self, url): + fn = _make_mock_url(url, filesyntax=False) + self._content = open(fn).read() + self.headers = {'content-length': len(self._content)} + + def raise_for_status(self): + pass + def iter_content(self, *args, **kwargs): + dummy = args + dummy = kwargs + return [self._content.encode("utf-8")] + + +class _MockRequestsSession: + def close(self): + pass + def head(self, url, *args, **kwargs): + dummy = args + dummy = kwargs + return _MockRequestsResponse(url) + def get(self, url, *args, **kwargs): + dummy = args + dummy = kwargs + return _MockRequestsResponse(url) + + +class _MockFTPSession: + def connect(self, *args, **kwargs): + pass + def login(self, *args, **kwargs): + pass + def voidcmd(self, *args, **kwargs): + pass + def quit(self, *args, **kwargs): + pass + def size(self, url): + path = _make_mock_url(url, filesyntax=False) + return os.path.getsize(path) + + +########################### +# Fetcher implementations # +########################### class _URLFetcher(object): """ @@ -168,7 +235,10 @@ class _HTTPURLFetcher(_URLFetcher): _session = None def _prepare(self): - self._session = requests.Session() + if _in_testsuite(): + self._session = _MockRequestsSession() + else: + self._session = requests.Session() def _cleanup(self): if self._session: @@ -227,7 +297,10 @@ class _FTPURLFetcher(_URLFetcher): try: parsed = urllib.parse.urlparse(self.location) - self._ftp = ftplib.FTP() + if _in_testsuite(): + self._ftp = _MockFTPSession() + else: + self._ftp = ftplib.FTP() username = urllib.parse.unquote(parsed.username or '') password = urllib.parse.unquote(parsed.password or '') self._ftp.connect(parsed.hostname, parsed.port or 0) @@ -242,6 +315,8 @@ class _FTPURLFetcher(_URLFetcher): """ Use urllib and ftplib to grab the file """ + if _in_testsuite(): + url = _make_mock_url(url, filesyntax=True) request = urllib.request.Request(url) urlobj = urllib.request.urlopen(request) size = self._ftp.size(urllib.parse.urlparse(url)[2])