tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_browser.py (22866B)


      1 # mypy: allow-untyped-defs
      2 
      3 import logging
      4 import os
      5 import inspect
      6 import requests
      7 import subprocess
      8 import sys
      9 from unittest import mock
     10 
     11 import pytest
     12 
     13 from packaging.specifiers import SpecifierSet
     14 from tools.wpt import browser
     15 
     16 
     17 logger = logging.getLogger()
     18 
     19 
     20 def test_all_browser_abc():
     21    # Make sure all subclasses of Browser implement all abstract methods
     22    # (except some known base classes). This is a basic sanity test in case
     23    # we change the ABC interface of Browser as we only instantiate some
     24    # products in unit tests.
     25    classes = inspect.getmembers(browser)
     26    for name, cls in classes:
     27        if cls in (browser.Browser, browser.ChromeChromiumBase, browser.ChromeAndroidBase):
     28            continue
     29        if inspect.isclass(cls) and issubclass(cls, browser.Browser):
     30            assert not inspect.isabstract(cls), "%s is abstract" % name
     31 
     32 
     33 def test_edge_webdriver_supports_browser():
     34    # MSEdgeDriver binary cannot be called.
     35    edge = browser.Edge(logger)
     36    edge.webdriver_version = mock.MagicMock(return_value=None)
     37    assert not edge.webdriver_supports_browser('/usr/bin/edgedriver', '/usr/bin/edge', 'stable')
     38 
     39    # Browser binary cannot be called.
     40    edge = browser.Edge(logger)
     41    edge.webdriver_version = mock.MagicMock(return_value='70.0.1')
     42    edge.version = mock.MagicMock(return_value=None)
     43    assert edge.webdriver_supports_browser('/usr/bin/edgedriver', '/usr/bin/edge', 'stable')
     44 
     45    # Browser version matches.
     46    edge = browser.Edge(logger)
     47    # Versions should be an exact match to be compatible.
     48    edge.webdriver_version = mock.MagicMock(return_value='70.1.5')
     49    edge.version = mock.MagicMock(return_value='70.1.5')
     50    assert edge.webdriver_supports_browser('/usr/bin/edgedriver', '/usr/bin/edge', 'stable')
     51 
     52    # Browser version doesn't match.
     53    edge = browser.Edge(logger)
     54    edge.webdriver_version = mock.MagicMock(return_value='70.0.1')
     55    edge.version = mock.MagicMock(return_value='69.0.1')
     56    assert not edge.webdriver_supports_browser('/usr/bin/edgedriver', '/usr/bin/edge', 'stable')
     57 
     58    # MSEdgeDriver version should match for MAJOR.MINOR.BUILD version.
     59    edge = browser.Edge(logger)
     60    edge.webdriver_version = mock.MagicMock(return_value='70.0.1.0')
     61    edge.version = mock.MagicMock(return_value='70.0.1.1 dev')
     62    assert edge.webdriver_supports_browser('/usr/bin/edgedriver', '/usr/bin/edge', 'dev')
     63    # Mismatching minor version should not match.
     64    edge.webdriver_version = mock.MagicMock(return_value='70.9.1')
     65    assert not edge.webdriver_supports_browser('/usr/bin/edgedriver', '/usr/bin/edge', 'dev')
     66 
     67 # On Windows, webdriver_version directly calls _get_fileversion, so there is no
     68 # logic to test there.
     69 @pytest.mark.skipif(sys.platform.startswith('win'), reason='just uses _get_fileversion on Windows')
     70 @mock.patch('tools.wpt.browser.call')
     71 def test_edge_webdriver_version(mocked_call):
     72    edge = browser.Edge(logger)
     73    webdriver_binary = '/usr/bin/edgedriver'
     74 
     75    # Working cases.
     76    mocked_call.return_value = 'Microsoft Edge WebDriver 84.0.4147.30'
     77    assert edge.webdriver_version(webdriver_binary) == '84.0.4147.30'
     78    mocked_call.return_value = 'Microsoft Edge WebDriver 87.0.1 (abcd1234-refs/branch-heads/4147@{#310})'
     79    assert edge.webdriver_version(webdriver_binary) == '87.0.1'
     80 
     81    # Various invalid version strings
     82    mocked_call.return_value = 'Edge 84.0.4147.30 (dev)'
     83    assert edge.webdriver_version(webdriver_binary) is None
     84    mocked_call.return_value = 'Microsoft Edge WebDriver New 84.0.4147.30'
     85    assert edge.webdriver_version(webdriver_binary) is None
     86    mocked_call.return_value = ''
     87    assert edge.webdriver_version(webdriver_binary) is None
     88 
     89    # The underlying subprocess call throws.
     90    mocked_call.side_effect = subprocess.CalledProcessError(5, 'cmd', output='Call failed')
     91    assert edge.webdriver_version(webdriver_binary) is None
     92 
     93 
     94 def test_chrome_webdriver_supports_browser():
     95    # ChromeDriver binary cannot be called.
     96    chrome = browser.Chrome(logger)
     97    chrome.webdriver_version = mock.MagicMock(return_value=None)
     98    assert not chrome.webdriver_supports_browser('/usr/bin/chromedriver', '/usr/bin/chrome', 'stable')
     99 
    100    # Browser binary cannot be called.
    101    chrome = browser.Chrome(logger)
    102    chrome.webdriver_version = mock.MagicMock(return_value='70.0.1')
    103    chrome.version = mock.MagicMock(return_value=None)
    104    assert chrome.webdriver_supports_browser('/usr/bin/chromedriver', '/usr/bin/chrome', 'stable')
    105 
    106    # Browser version matches.
    107    chrome = browser.Chrome(logger)
    108    # Versions should be an exact match to be compatible.
    109    chrome.webdriver_version = mock.MagicMock(return_value='70.1.5')
    110    chrome.version = mock.MagicMock(return_value='70.1.5')
    111    assert chrome.webdriver_supports_browser('/usr/bin/chromedriver', '/usr/bin/chrome', 'stable')
    112 
    113    # Browser version doesn't match.
    114    chrome = browser.Chrome(logger)
    115    chrome.webdriver_version = mock.MagicMock(return_value='70.0.1')
    116    chrome.version = mock.MagicMock(return_value='69.0.1')
    117    assert not chrome.webdriver_supports_browser('/usr/bin/chromedriver', '/usr/bin/chrome', 'stable')
    118 
    119    # ChromeDriver version should match for MAJOR.MINOR.BUILD version.
    120    chrome = browser.Chrome(logger)
    121    chrome.webdriver_version = mock.MagicMock(return_value='70.0.1.0')
    122    chrome.version = mock.MagicMock(return_value='70.0.1.1 dev')
    123    assert chrome.webdriver_supports_browser('/usr/bin/chromedriver', '/usr/bin/chrome', 'dev')
    124    # Matching major version should match.
    125    chrome.webdriver_version = mock.MagicMock(return_value='70.9.1')
    126    assert chrome.webdriver_supports_browser('/usr/bin/chromedriver', '/usr/bin/chrome', 'dev')
    127 
    128 
    129 def test_chromium_webdriver_supports_browser():
    130    # ChromeDriver binary cannot be called.
    131    chromium = browser.Chromium(logger)
    132    chromium.webdriver_version = mock.MagicMock(return_value=None)
    133    assert not chromium.webdriver_supports_browser('/usr/bin/chromedriver', '/usr/bin/chrome')
    134 
    135    # Browser binary cannot be called.
    136    chromium = browser.Chromium(logger)
    137    chromium.webdriver_version = mock.MagicMock(return_value='70.0.1')
    138    chromium.version = mock.MagicMock(return_value=None)
    139    assert chromium.webdriver_supports_browser('/usr/bin/chromedriver', '/usr/bin/chrome')
    140 
    141    # Browser version matches.
    142    chromium = browser.Chromium(logger)
    143    chromium.webdriver_version = mock.MagicMock(return_value='70.0.1')
    144    chromium.version = mock.MagicMock(return_value='70.0.1')
    145    assert chromium.webdriver_supports_browser('/usr/bin/chromedriver', '/usr/bin/chrome')
    146 
    147    # Browser version doesn't match.
    148    chromium = browser.Chromium(logger)
    149    chromium.webdriver_version = mock.MagicMock(return_value='70.0.1')
    150    chromium.version = mock.MagicMock(return_value='69.0.1')
    151    assert not chromium.webdriver_supports_browser('/usr/bin/chromedriver', '/usr/bin/chrome', 'stable')
    152 
    153 
    154 # On Windows, webdriver_version directly calls _get_fileversion, so there is no
    155 # logic to test there.
    156 @pytest.mark.skipif(sys.platform.startswith('win'), reason='just uses _get_fileversion on Windows')
    157 @mock.patch('tools.wpt.browser.call')
    158 def test_chrome_webdriver_version(mocked_call):
    159    chrome = browser.Chrome(logger)
    160    webdriver_binary = '/usr/bin/chromedriver'
    161 
    162    # Working cases.
    163    mocked_call.return_value = 'ChromeDriver 84.0.4147.30'
    164    assert chrome.webdriver_version(webdriver_binary) == '84.0.4147.30'
    165    mocked_call.return_value = 'ChromeDriver 87.0.1 (abcd1234-refs/branch-heads/4147@{#310})'
    166    assert chrome.webdriver_version(webdriver_binary) == '87.0.1'
    167 
    168    # Various invalid version strings
    169    mocked_call.return_value = 'Chrome 84.0.4147.30 (dev)'
    170    assert chrome.webdriver_version(webdriver_binary) is None
    171    mocked_call.return_value = 'ChromeDriver New 84.0.4147.30'
    172    assert chrome.webdriver_version(webdriver_binary) is None
    173    mocked_call.return_value = ''
    174    assert chrome.webdriver_version(webdriver_binary) is None
    175 
    176    # The underlying subprocess call throws.
    177    mocked_call.side_effect = subprocess.CalledProcessError(5, 'cmd', output='Call failed')
    178    assert chrome.webdriver_version(webdriver_binary) is None
    179 
    180 
    181 @mock.patch('subprocess.check_output')
    182 def test_safari_version(mocked_check_output):
    183    safari = browser.Safari(logger)
    184 
    185    # Safari
    186    mocked_check_output.return_value = b'Included with Safari 12.1 (14607.1.11)'
    187    assert safari.version(webdriver_binary="safaridriver") == '12.1 (14607.1.11)'
    188 
    189    # Safari Technology Preview
    190    mocked_check_output.return_value = b'Included with Safari Technology Preview (Release 67, 13607.1.9.0.1)'
    191    assert safari.version(webdriver_binary="safaridriver") == 'Technology Preview (Release 67, 13607.1.9.0.1)'
    192 
    193 @mock.patch('subprocess.check_output')
    194 def test_safari_version_errors(mocked_check_output):
    195    safari = browser.Safari(logger)
    196 
    197    # No webdriver_binary
    198    assert safari.version() is None
    199 
    200    # `safaridriver --version` return gibberish
    201    mocked_check_output.return_value = b'gibberish'
    202    assert safari.version(webdriver_binary="safaridriver") is None
    203 
    204    # `safaridriver --version` fails (as it does for Safari <=12.0)
    205    mocked_check_output.return_value = b'dummy'
    206    mocked_check_output.side_effect = subprocess.CalledProcessError(1, 'cmd')
    207    assert safari.version(webdriver_binary="safaridriver") is None
    208 
    209 
    210 @pytest.mark.parametrize(
    211    "page_path",
    212    sorted(
    213        p.path
    214        for p in os.scandir(os.path.join(os.path.dirname(__file__), "safari-downloads"))
    215        if p.name.endswith(".html")
    216    ),
    217 )
    218 @mock.patch("tools.wpt.browser.get")
    219 def test_safari_find_downloads_stp(mocked_get, page_path):
    220    safari = browser.Safari(logger)
    221 
    222    # Setup mock
    223    response = requests.models.Response()
    224    response.status_code = 200
    225    response.encoding = "utf-8"
    226    with open(page_path, "rb") as fp:
    227        response._content = fp.read()
    228    mocked_get.return_value = response
    229 
    230    downloads = safari._find_downloads()
    231 
    232    if page_path.endswith(
    233        (
    234            "2022-07-05.html",
    235        )
    236    ):
    237        # occasionally STP is only shipped for a single OS version
    238        assert len(downloads) == 1
    239    else:
    240        assert len(downloads) == 2
    241 
    242 
    243 @mock.patch("tools.wpt.browser.get")
    244 def test_safari_find_downloads_stp_20180517(mocked_get):
    245    safari = browser.Safari(logger)
    246    page_path = os.path.join(os.path.dirname(__file__), "safari-downloads", "2018-05-17.html")
    247 
    248    # Setup mock
    249    response = requests.models.Response()
    250    response.status_code = 200
    251    response.encoding = "utf-8"
    252    with open(page_path, "rb") as fp:
    253        response._content = fp.read()
    254    mocked_get.return_value = response
    255 
    256    downloads = safari._find_downloads()
    257 
    258    assert len(downloads) == 2
    259 
    260    assert downloads[0][0] == SpecifierSet("==10.13.*")
    261    assert "10.12" not in downloads[0][0]
    262    assert "10.13" in downloads[0][0]
    263    assert "10.13.3" in downloads[0][0]
    264    assert "10.14" not in downloads[0][0]
    265 
    266    assert downloads[1][0] == SpecifierSet("~=10.12.6")
    267    assert "10.12" not in downloads[1][0]
    268    assert "10.12.6" in downloads[1][0]
    269    assert "10.12.9" in downloads[1][0]
    270    assert "10.13" not in downloads[1][0]
    271 
    272 
    273 @mock.patch("tools.wpt.browser.get")
    274 def test_safari_find_downloads_stp_20220529(mocked_get):
    275    safari = browser.Safari(logger)
    276    page_path = os.path.join(os.path.dirname(__file__), "safari-downloads", "2022-05-29.html")
    277 
    278    # Setup mock
    279    response = requests.models.Response()
    280    response.status_code = 200
    281    response.encoding = "utf-8"
    282    with open(page_path, "rb") as fp:
    283        response._content = fp.read()
    284    mocked_get.return_value = response
    285 
    286    downloads = safari._find_downloads()
    287 
    288    assert len(downloads) == 2
    289 
    290    assert downloads[0][0] == SpecifierSet("==12.*")
    291    assert "11.4" not in downloads[0][0]
    292    assert "12.0" in downloads[0][0]
    293    assert "12.5" in downloads[0][0]
    294    assert "13.0" not in downloads[0][0]
    295 
    296    assert downloads[1][0] == SpecifierSet("==11.*")
    297    assert "10.15.7" not in downloads[1][0]
    298    assert "11.0.1" in downloads[1][0]
    299    assert "11.3" in downloads[1][0]
    300    assert "11.5" in downloads[1][0]
    301    assert "12.0" not in downloads[1][0]
    302 
    303 
    304 @mock.patch("tools.wpt.browser.get")
    305 def test_safari_find_downloads_stp_20220707(mocked_get):
    306    safari = browser.Safari(logger)
    307    page_path = os.path.join(os.path.dirname(__file__), "safari-downloads", "2022-07-07.html")
    308 
    309    # Setup mock
    310    response = requests.models.Response()
    311    response.status_code = 200
    312    response.encoding = "utf-8"
    313    with open(page_path, "rb") as fp:
    314        response._content = fp.read()
    315    mocked_get.return_value = response
    316 
    317    downloads = safari._find_downloads()
    318 
    319    assert len(downloads) == 2
    320 
    321    assert downloads[0][0] == SpecifierSet("==13.*")
    322    assert "12.4" not in downloads[0][0]
    323    assert "13.0" in downloads[0][0]
    324    assert "13.5" in downloads[0][0]
    325    assert "14.0" not in downloads[0][0]
    326 
    327    assert downloads[1][0] == SpecifierSet("~=12.3")
    328    assert "11.5" not in downloads[1][0]
    329    assert "12.2" not in downloads[1][0]
    330    assert "12.3" in downloads[1][0]
    331    assert "12.5" in downloads[1][0]
    332    assert "13.0" not in downloads[1][0]
    333 
    334 
    335 @mock.patch('subprocess.check_output')
    336 def test_webkitgtk_minibrowser_version(mocked_check_output):
    337    webkitgtk_minibrowser = browser.WebKitGTKMiniBrowser(logger)
    338 
    339    # stable version
    340    mocked_check_output.return_value = b'WebKitGTK 2.26.1\n'
    341    assert webkitgtk_minibrowser.version(binary='MiniBrowser') == '2.26.1'
    342 
    343    # nightly version
    344    mocked_check_output.return_value = b'WebKitGTK 2.47.1 (286783@main)\n'
    345    assert webkitgtk_minibrowser.version(binary='MiniBrowser') == '2.47.1 (286783@main)'
    346 
    347 
    348 @mock.patch('subprocess.check_output')
    349 def test_webkitgtk_minibrowser_version_errors(mocked_check_output):
    350    webkitgtk_minibrowser = browser.WebKitGTKMiniBrowser(logger)
    351 
    352    # No binary
    353    assert webkitgtk_minibrowser.version() is None
    354 
    355    # `MiniBrowser --version` return gibberish
    356    mocked_check_output.return_value = b'gibberish'
    357    assert webkitgtk_minibrowser.version(binary='MiniBrowser') is None
    358 
    359    # `MiniBrowser --version` fails (as it does for MiniBrowser <= 2.26.0)
    360    mocked_check_output.return_value = b'dummy'
    361    mocked_check_output.side_effect = subprocess.CalledProcessError(1, 'cmd')
    362    assert webkitgtk_minibrowser.version(binary='MiniBrowser') is None
    363 
    364 
    365 # The test below doesn't work on Windows because find_binary()
    366 # on Windows only works if the binary name ends with a ".exe" suffix.
    367 # But, WebKitGTK itself doesn't support Windows, so lets skip the test.
    368 @pytest.mark.skipif(sys.platform.startswith('win'), reason='test not needed on Windows')
    369 @mock.patch('os.path.isdir', return_value=True)
    370 @mock.patch('os.access', return_value=True)
    371 @mock.patch('shutil.which')
    372 @mock.patch('os.listdir')
    373 @mock.patch('os.path.isfile')
    374 def test_webkitgtk_minibrowser_find_binary(mocked_os_path_isfile, mocked_os_listdir, mocked_which, _mocked_os_access, _mocked_os_isdir):
    375    webkitgtk_minibrowser = browser.WebKitGTKMiniBrowser(logger)
    376 
    377    # No WebKitGTK MiniBrowser found (WPE one shouldn't match)
    378    mocked_os_path_isfile.side_effect = lambda path: path == '/usr/libexec/wpe-webkit-1.0/MiniBrowser'
    379    mocked_os_listdir.side_effect = lambda contents: ['wpe-webkit-1.0', 'webkitgtk-6.0', 'webkit2gtk-4.0']
    380    mocked_which.side_effect = lambda found: None
    381    assert webkitgtk_minibrowser.find_binary() is None
    382 
    383    # Found on the default Fedora path
    384    fedora_minibrowser_path = '/usr/libexec/webkit2gtk-4.0/MiniBrowser'
    385    mocked_os_path_isfile.side_effect = lambda path: path == fedora_minibrowser_path
    386    mocked_os_listdir.side_effect = lambda contents: ['wpe-webkit-1.0', 'webkitgtk-6.0', 'webkit2gtk-4.0']
    387    mocked_which.side_effect = lambda found: None
    388    assert webkitgtk_minibrowser.find_binary() == fedora_minibrowser_path
    389 
    390    # Found on the default Debian path for AMD64 (gcc not available)
    391    debian_minibrowser_path_amd64 = '/usr/lib/x86_64-linux-gnu/webkit2gtk-4.0/MiniBrowser'
    392    mocked_os_path_isfile.side_effect = lambda path: path == debian_minibrowser_path_amd64
    393    mocked_os_listdir.side_effect = lambda contents: ['wpe-webkit-1.0', 'webkitgtk-6.0', 'webkit2gtk-4.0']
    394    mocked_which.side_effect = lambda found: None
    395    assert webkitgtk_minibrowser.find_binary() == debian_minibrowser_path_amd64
    396 
    397    # Found on the default Debian path for AMD64 (gcc available but gives an error)
    398    debian_minibrowser_path_amd64 = '/usr/lib/x86_64-linux-gnu/webkit2gtk-4.0/MiniBrowser'
    399    mocked_os_path_isfile.side_effect = lambda path: path in [debian_minibrowser_path_amd64, '/usr/bin/gcc']
    400    mocked_os_listdir.side_effect = lambda contents: ['wpe-webkit-1.0', 'webkitgtk-6.0', 'webkit2gtk-4.0']
    401    mocked_which.side_effect = lambda found: '/usr/bin/gcc'
    402    with mock.patch('subprocess.check_output', return_value = b'error', side_effect = subprocess.CalledProcessError(1, 'cmd')):
    403        assert webkitgtk_minibrowser.find_binary() == debian_minibrowser_path_amd64
    404 
    405    # Found on the default Debian path for ARM64 (gcc available)
    406    debian_minibrowser_path_arm64 = '/usr/lib/aarch64-linux-gnu/webkit2gtk-4.0/MiniBrowser'
    407    mocked_os_path_isfile.side_effect = lambda path: path in [debian_minibrowser_path_arm64, '/usr/bin/gcc']
    408    mocked_os_listdir.side_effect = lambda contents: sorted(['wpe-webkit-1.0', 'webkitgtk-6.0', 'webkit2gtk-4.0'])
    409    mocked_which.side_effect = lambda found: '/usr/bin/gcc'
    410    with mock.patch('subprocess.check_output', return_value = b'aarch64-linux-gnu'):
    411        assert webkitgtk_minibrowser.find_binary() == debian_minibrowser_path_arm64
    412 
    413    # Find first the MiniBrowser on the directory with the higher number in case two available
    414    mocked_os_path_isfile.side_effect = lambda path: True
    415    mocked_os_listdir.side_effect = lambda contents: ['wpe-webkit-1.0', 'webkitgtk-6.0', 'webkit2gtk-4.0']
    416    mocked_which.side_effect = lambda found: None
    417    assert webkitgtk_minibrowser.find_binary() == '/usr/libexec/webkitgtk-6.0/MiniBrowser'
    418 
    419 
    420 @mock.patch('subprocess.check_output')
    421 def test_wpewebkit_minibrowser_version(mocked_check_output):
    422    wpewebkit_minibrowser = browser.WPEWebKitMiniBrowser(logger)
    423 
    424    # stable version
    425    mocked_check_output.return_value = b'WPE WebKit 2.26.1\n'
    426    assert wpewebkit_minibrowser.version(binary='MiniBrowser') == '2.26.1'
    427 
    428    # nightly version
    429    mocked_check_output.return_value = b'WPE WebKit 2.47.1 (286783@main)\n'
    430    assert wpewebkit_minibrowser.version(binary='MiniBrowser') == '2.47.1 (286783@main)'
    431 
    432 
    433 @mock.patch('subprocess.check_output')
    434 def test_wpewebkit_minibrowser_version_errors(mocked_check_output):
    435    wpewebkit_minibrowser = browser.WPEWebKitMiniBrowser(logger)
    436 
    437    # No binary
    438    assert wpewebkit_minibrowser.version() is None
    439 
    440    # `MiniBrowser --version` return gibberish
    441    mocked_check_output.return_value = b'gibberish'
    442    assert wpewebkit_minibrowser.version(binary='MiniBrowser') is None
    443 
    444    # `MiniBrowser --version` fails (as it does for MiniBrowser <= 2.26.0)
    445    mocked_check_output.return_value = b'dummy'
    446    mocked_check_output.side_effect = subprocess.CalledProcessError(1, 'cmd')
    447    assert wpewebkit_minibrowser.version(binary='MiniBrowser') is None
    448 
    449 
    450 # The test below doesn't work on Windows because find_binary()
    451 # on Windows only works if the binary name ends with a ".exe" suffix.
    452 # But, WPE WebKit itself doesn't support Windows, so lets skip the test.
    453 @pytest.mark.skipif(sys.platform.startswith('win'), reason='test not needed on Windows')
    454 @mock.patch('os.path.isdir', return_value=True)
    455 @mock.patch('os.access', return_value=True)
    456 @mock.patch('shutil.which')
    457 @mock.patch('os.listdir')
    458 @mock.patch('os.path.isfile')
    459 def test_wpewebkit_minibrowser_find_binary(mocked_os_path_isfile, mocked_os_listdir, mocked_which, _mocked_os_access, _mocked_os_isdir):
    460    wpewebkit_minibrowser = browser.WPEWebKitMiniBrowser(logger)
    461 
    462    # No WPE MiniBrowser found (WebKitGTK one shouldn't match)
    463    mocked_os_path_isfile.side_effect = lambda path: path == '/usr/libexec/wpewebkit-6.0/MiniBrowser'
    464    mocked_os_listdir.side_effect = lambda contents: ['wpewebkit-6.0', 'webkit2gtk-4.0', 'wpe-webkit-1.0']
    465    mocked_which.side_effect = lambda found: None
    466    assert wpewebkit_minibrowser.find_binary() is None
    467 
    468    # Found on the default Arch path
    469    arch_minibrowser_path = '/usr/lib/wpe-webkit-1.0/MiniBrowser'
    470    mocked_os_path_isfile.side_effect = lambda path: path == arch_minibrowser_path
    471    mocked_os_listdir.side_effect = lambda contents: ['wpewebkit-6.0', 'webkit2gtk-4.0', 'wpe-webkit-1.0']
    472    mocked_which.side_effect = lambda found: None
    473    assert wpewebkit_minibrowser.find_binary() == arch_minibrowser_path
    474 
    475    # Found on the default Debian path for AMD64 (gcc not available)
    476    debian_minibrowser_path_amd64 = '/usr/lib/x86_64-linux-gnu/wpe-webkit-1.0/MiniBrowser'
    477    mocked_os_path_isfile.side_effect = lambda path: path == debian_minibrowser_path_amd64
    478    mocked_os_listdir.side_effect = lambda contents: ['wpewebkit-6.0', 'webkit2gtk-4.0', 'wpe-webkit-1.0']
    479    mocked_which.side_effect = lambda found: None
    480    assert wpewebkit_minibrowser.find_binary() == debian_minibrowser_path_amd64
    481 
    482    # Found on the default Debian path for AMD64 (gcc available but gives an error)
    483    debian_minibrowser_path_amd64 = '/usr/lib/x86_64-linux-gnu/wpe-webkit-1.0/MiniBrowser'
    484    mocked_os_path_isfile.side_effect = lambda path: path in [debian_minibrowser_path_amd64, '/usr/bin/gcc']
    485    mocked_os_listdir.side_effect = lambda contents: ['wpewebkit-6.0', 'webkit2gtk-4.0', 'wpe-webkit-1.0']
    486    mocked_which.side_effect = lambda found: '/usr/bin/gcc'
    487    with mock.patch('subprocess.check_output', return_value = b'error', side_effect = subprocess.CalledProcessError(1, 'cmd')):
    488        assert wpewebkit_minibrowser.find_binary() == debian_minibrowser_path_amd64
    489 
    490    # Found on the default Debian path for ARM64 (gcc available)
    491    debian_minibrowser_path_arm64 = '/usr/lib/aarch64-linux-gnu/wpe-webkit-1.0/MiniBrowser'
    492    mocked_os_path_isfile.side_effect = lambda path: path in [debian_minibrowser_path_arm64, '/usr/bin/gcc']
    493    mocked_os_listdir.side_effect = lambda contents: ['wpewebkit-6.0', 'webkit2gtk-4.0', 'wpe-webkit-1.0']
    494    mocked_which.side_effect = lambda found: '/usr/bin/gcc'
    495    with mock.patch('subprocess.check_output', return_value = b'aarch64-linux-gnu'):
    496        assert wpewebkit_minibrowser.find_binary() == debian_minibrowser_path_arm64
    497 
    498    # Find first the MiniBrowser on the directory with the higher number in case two available
    499    mocked_os_path_isfile.side_effect = lambda path: True
    500    mocked_os_listdir.side_effect = lambda contents: sorted(['wpewebkit-6.0', 'webkit2gtk-4.0', 'wpe-webkit-2.0', 'wpe-webkit-1.0'])
    501    mocked_which.side_effect = lambda found: None
    502    assert wpewebkit_minibrowser.find_binary() == '/usr/libexec/wpe-webkit-2.0/MiniBrowser'