From 9e9dfb86e39462a49922baf55f95d714dd0bc7c2 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Thu, 20 Aug 2020 22:37:25 -0700 Subject: [PATCH 01/17] Allow tor files to be in /usr/share or /usr/local/share in tests --- tests/test_cli_common.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/test_cli_common.py b/tests/test_cli_common.py index 3592d1ba..eb3ece04 100644 --- a/tests/test_cli_common.py +++ b/tests/test_cli_common.py @@ -235,8 +235,14 @@ class TestGetTorPaths: ) = common_obj.get_tor_paths() assert os.path.basename(tor_path) == "tor" - assert tor_geo_ip_file_path == "/usr/share/tor/geoip" - assert tor_geo_ipv6_file_path == "/usr/share/tor/geoip6" + assert ( + tor_geo_ip_file_path == "/usr/share/tor/geoip" + or tor_geo_ip_file_path == "/usr/local/share/tor/geoip" + ) + assert ( + tor_geo_ipv6_file_path == "/usr/share/tor/geoip6" + or tor_geo_ipv6_file_path == "/usr/local/share/tor/geoip6" + ) # @pytest.mark.skipif(sys.platform != 'Windows', reason='requires Windows') ? def test_get_tor_paths_windows(self, platform_windows, common_obj, sys_frozen): From 1a6c2f3d6382a210398541c86c6eae8ee125aaf7 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Thu, 20 Aug 2020 22:53:43 -0700 Subject: [PATCH 02/17] Fix base GUI test to take account that the macOS version has separate Add Files and Add Folder --- tests/gui_base_test.py | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/tests/gui_base_test.py b/tests/gui_base_test.py index ab5df8a1..0d2d4fa1 100644 --- a/tests/gui_base_test.py +++ b/tests/gui_base_test.py @@ -8,6 +8,7 @@ import shutil import base64 import tempfile import secrets +import platform from PyQt5 import QtCore, QtTest, QtWidgets @@ -275,9 +276,17 @@ class GuiBaseTest(unittest.TestCase): def add_button_visible(self, tab): """Test that the add button should be visible""" - self.assertTrue( - tab.get_mode().server_status.file_selection.add_button.isVisible() - ) + if platform.system() == "Darwin": + self.assertTrue( + tab.get_mode().server_status.file_selection.add_files_button.isVisible() + ) + self.assertTrue( + tab.get_mode().server_status.file_selection.add_folder_button.isVisible() + ) + else: + self.assertTrue( + tab.get_mode().server_status.file_selection.add_button.isVisible() + ) def url_description_shown(self, tab): """Test that the URL label is showing""" @@ -299,7 +308,10 @@ class GuiBaseTest(unittest.TestCase): def have_show_qr_code_button(self, tab): """Test that the Show QR Code URL button is shown and that it loads a QR Code Dialog""" - self.assertTrue(tab.get_mode().server_status.show_url_qr_code_button.isVisible()) + self.assertTrue( + tab.get_mode().server_status.show_url_qr_code_button.isVisible() + ) + def accept_dialog(): window = tab.common.gui.qtapp.activeWindow() if window: @@ -358,11 +370,15 @@ class GuiBaseTest(unittest.TestCase): ): tab.get_mode().server_status.server_button.click() self.assertEqual(tab.get_mode().server_status.status, 0) - self.assertFalse(tab.get_mode().server_status.show_url_qr_code_button.isVisible()) + self.assertFalse( + tab.get_mode().server_status.show_url_qr_code_button.isVisible() + ) self.assertFalse(tab.get_mode().server_status.copy_url_button.isVisible()) self.assertFalse(tab.get_mode().server_status.url.isVisible()) self.assertFalse(tab.get_mode().server_status.url_description.isVisible()) - self.assertFalse(tab.get_mode().server_status.copy_hidservauth_button.isVisible()) + self.assertFalse( + tab.get_mode().server_status.copy_hidservauth_button.isVisible() + ) def web_server_is_stopped(self, tab): """Test that the web server also stopped""" @@ -406,9 +422,17 @@ class GuiBaseTest(unittest.TestCase): def add_remove_buttons_hidden(self, tab): """Test that the add and remove buttons are hidden when the server starts""" - self.assertFalse( - tab.get_mode().server_status.file_selection.add_button.isVisible() - ) + if platform.system() == "Darwin": + self.assertFalse( + tab.get_mode().server_status.file_selection.add_files_button.isVisible() + ) + self.assertFalse( + tab.get_mode().server_status.file_selection.add_folder_button.isVisible() + ) + else: + self.assertFalse( + tab.get_mode().server_status.file_selection.add_button.isVisible() + ) self.assertFalse( tab.get_mode().server_status.file_selection.remove_button.isVisible() ) From c0faa4a3523da88a3141a1c93eae2ae23bad1532 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 21 Aug 2020 14:49:23 -0400 Subject: [PATCH 03/17] Only import pwd in macOS, because it does not exist in Windows --- onionshare/mode_settings.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/onionshare/mode_settings.py b/onionshare/mode_settings.py index 8216c1d8..f141f8c5 100644 --- a/onionshare/mode_settings.py +++ b/onionshare/mode_settings.py @@ -18,8 +18,11 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ import os -import pwd import json +import platform + +if platform.system() == "Darwin": + import pwd class ModeSettings: From 18d63521ac46d4be105bd995c7278a745e3dad2f Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 21 Aug 2020 14:49:33 -0400 Subject: [PATCH 04/17] Update windows build instructions --- BUILD.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/BUILD.md b/BUILD.md index da38590f..f85b22d1 100644 --- a/BUILD.md +++ b/BUILD.md @@ -150,9 +150,11 @@ Now you should have `dist/OnionShare.pkg`. ### Setting up your dev environment +These instructions include adding folders to the path in Windows. To do this, go to Start and type "advanced system settings", and open "View advanced system settings" in the Control Panel. Click Environment Variables. Under "System variables" double-click on Path. From there you can add and remove folders that are available in the PATH. + Download Python 3.7.4, 32-bit (x86) from https://www.python.org/downloads/release/python-374/. I downloaded `python-3.7.4.exe`. When installing it, make sure to check the "Add Python 3.7 to PATH" checkbox on the first page of the installer. -Install the Qt 5.13.1 from https://www.qt.io/offline-installers. I downloaded `qt-opensource-windows-x86-5.13.1.exe`. In the installer, you can skip making an account, and all you need `Qt` > `Qt 5.13.1` > `MSVC 2017 32-bit`. +Install the Qt 5.14.0 from https://www.qt.io/offline-installers. I downloaded `qt-opensource-windows-x86-5.14.0.exe`. In the installer, you can skip making an account, and all you need `Qt` > `Qt 5.14.0` > `MSVC 2017 32-bit`. Install [poetry](https://python-poetry.org/). Open PowerShell, and run: @@ -160,7 +162,7 @@ Install [poetry](https://python-poetry.org/). Open PowerShell, and run: (Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py -UseBasicParsing).Content | python ``` -And add `%USERPROFILE%\.poetry\bin` to your path. Then open a command prompt and cd to the `dangerzone` folder, and install the poetry dependencies: +Then open a Command Prompt and cd to the `onionshare` folder, and install the poetry dependencies: ``` poetry install @@ -175,8 +177,6 @@ poetry run python dev_scripts\onionshare-gui #### If you want to build a .exe -These instructions include adding folders to the path in Windows. To do this, go to Start and type "advanced system settings", and open "View advanced system settings" in the Control Panel. Click Environment Variables. Under "System variables" double-click on Path. From there you can add and remove folders that are available in the PATH. - Download and install 7-Zip from http://www.7-zip.org/download.html. I downloaded `7z1900.exe`. Download and install the standalone [Windows 10 SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk). Note that you may not need this if you already have Visual Studio. From 1b9659395ec6e045394f8ab74880e45698906657 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 21 Aug 2020 16:17:37 -0400 Subject: [PATCH 05/17] Change how TestLog works to also work in Windows --- tests/test_cli_common.py | 44 ++++++++-------------------------------- 1 file changed, 8 insertions(+), 36 deletions(-) diff --git a/tests/test_cli_common.py b/tests/test_cli_common.py index eb3ece04..650854f1 100644 --- a/tests/test_cli_common.py +++ b/tests/test_cli_common.py @@ -29,13 +29,6 @@ import zipfile import pytest -LOG_MSG_REGEX = re.compile( - r""" - ^\[Jun\ 06\ 2013\ 11:05:00\] - \ TestModule\.\.dummy_func - \ at\ 0x[a-f0-9]+>(:\ TEST_MSG)?$""", - re.VERBOSE, -) PASSWORD_REGEX = re.compile(r"^([a-z]+)(-[a-z]+)?-([a-z]+)(-[a-z]+)?$") @@ -194,7 +187,7 @@ class TestGetResourcePath: ) == os.path.join(prefix, "test_filename") def test_linux(self, common_obj, platform_linux, sys_argv_sys_prefix): - prefix = os.path.join(sys.prefix, "share/onionshare") + prefix = os.path.join(sys.prefix, "share", "onionshare") assert common_obj.get_resource_path( os.path.join(prefix, "test_filename") ) == os.path.join(prefix, "test_filename") @@ -207,7 +200,7 @@ class TestGetResourcePath: class TestGetTorPaths: - # @pytest.mark.skipif(sys.platform != 'Darwin', reason='requires MacOS') ? + @pytest.mark.skipif(sys.platform != "Darwin", reason="requires MacOS") def test_get_tor_paths_darwin( self, platform_darwin, common_obj, sys_frozen, sys_meipass ): @@ -225,7 +218,7 @@ class TestGetTorPaths: obfs4proxy_file_path, ) - # @pytest.mark.skipif(sys.platform != 'Linux', reason='requires Linux') ? + @pytest.mark.skipif(sys.platform != "Linux", reason="requires Linux") def test_get_tor_paths_linux(self, platform_linux, common_obj): ( tor_path, @@ -244,7 +237,7 @@ class TestGetTorPaths: or tor_geo_ipv6_file_path == "/usr/local/share/tor/geoip6" ) - # @pytest.mark.skipif(sys.platform != 'Windows', reason='requires Windows') ? + @pytest.mark.skipif(sys.platform != "win32", reason="requires Windows") def test_get_tor_paths_windows(self, platform_windows, common_obj, sys_frozen): base_path = os.path.join( os.path.dirname(os.path.dirname(common_obj.get_resource_path(""))), "tor" @@ -287,36 +280,15 @@ class TestHumanReadableFilesize: class TestLog: - @pytest.mark.parametrize( - "test_input", - ( - ( - "[Jun 06 2013 11:05:00]" - " TestModule..dummy_func" - " at 0xdeadbeef>" - ), - ( - "[Jun 06 2013 11:05:00]" - " TestModule..dummy_func" - " at 0xdeadbeef>: TEST_MSG" - ), - ), - ) - def test_log_msg_regex(self, test_input): - assert bool(LOG_MSG_REGEX.match(test_input)) - def test_output(self, common_obj, time_strftime): - def dummy_func(): - pass - common_obj.verbose = True # From: https://stackoverflow.com/questions/1218933 with io.StringIO() as buf, contextlib.redirect_stdout(buf): - common_obj.log("TestModule", dummy_func) - common_obj.log("TestModule", dummy_func, "TEST_MSG") + common_obj.log("TestModule", "dummy_func") + common_obj.log("TestModule", "dummy_func", "TEST_MSG") output = buf.getvalue() line_one, line_two, _ = output.split("\n") - assert LOG_MSG_REGEX.match(line_one) - assert LOG_MSG_REGEX.match(line_two) + assert line_one == "[Jun 06 2013 11:05:00] TestModule.dummy_func" + assert line_two == "[Jun 06 2013 11:05:00] TestModule.dummy_func: TEST_MSG" From b1a8c1054bcb194138d40119af46c7a24a4d426f Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 21 Aug 2020 16:42:20 -0400 Subject: [PATCH 06/17] Fix settings tests for Windows --- tests/test_cli_settings.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/test_cli_settings.py b/tests/test_cli_settings.py index 7a1e8de5..089c7416 100644 --- a/tests/test_cli_settings.py +++ b/tests/test_cli_settings.py @@ -20,6 +20,7 @@ along with this program. If not, see . import json import os import tempfile +import sys import pytest @@ -135,18 +136,27 @@ class TestSettings: settings_obj.set("socks_port", "NON_INTEGER") assert settings_obj._settings["socks_port"] == 9050 + @pytest.mark.skipif(sys.platform != "Darwin", reason="requires Darwin") def test_filename_darwin(self, monkeypatch, platform_darwin): obj = settings.Settings(common.Common()) assert obj.filename == os.path.expanduser( "~/Library/Application Support/OnionShare-testdata/onionshare.json" ) + @pytest.mark.skipif(sys.platform != "Linux", reason="requires Linux") def test_filename_linux(self, monkeypatch, platform_linux): obj = settings.Settings(common.Common()) assert obj.filename == os.path.expanduser( "~/.config/onionshare-testdata/onionshare.json" ) + @pytest.mark.skipif(sys.platform != "win32", reason="requires Windows") + def test_filename_windows(self, monkeypatch, platform_windows): + obj = settings.Settings(common.Common()) + assert obj.filename == os.path.expanduser( + "~\\AppData\\Roaming\\OnionShare-testdata\\onionshare.json" + ) + def test_set_custom_bridge(self, settings_obj): settings_obj.set( "tor_bridges_use_custom_bridges", From 176368a22b89cd83dc11bfefe7baa80dcfdd7bec Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 21 Aug 2020 17:38:25 -0400 Subject: [PATCH 07/17] Close test temporary file before returning, to avoid permission denied error in windows --- tests/conftest.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index 200f526d..ba0f1e72 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -98,9 +98,10 @@ def temp_file_1024_delete(temp_dir): The temporary file will be deleted after fixture usage. """ - with tempfile.NamedTemporaryFile(dir=temp_dir) as tmp_file: + with tempfile.NamedTemporaryFile(dir=temp_dir, delete=False) as tmp_file: tmp_file.write(b"*" * 1024) tmp_file.flush() + tmp_file.close() yield tmp_file.name From c6f1eb4766296e7dd98c9d3b466afab099dd27d8 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 21 Aug 2020 18:33:45 -0400 Subject: [PATCH 08/17] Fix more tempfile already open problems in Windows tests --- tests/test_gui_share.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tests/test_gui_share.py b/tests/test_gui_share.py index 846a5034..58c90977 100644 --- a/tests/test_gui_share.py +++ b/tests/test_gui_share.py @@ -83,13 +83,13 @@ class TestShare(GuiBaseTest): ), ) - tmp_file = tempfile.NamedTemporaryFile() - with open(tmp_file.name, "wb") as f: - f.write(r.content) + tmp_file = tempfile.NamedTemporaryFile("wb", delete=False) + tmp_file.write(r.content) + tmp_file.close() - zip = zipfile.ZipFile(tmp_file.name) + z = zipfile.ZipFile(tmp_file.name) QtTest.QTest.qWait(50) - self.assertEqual("onionshare", zip.read("test.txt").decode("utf-8")) + self.assertEqual("onionshare", z.read("test.txt").decode("utf-8")) QtTest.QTest.qWait(500) @@ -135,9 +135,8 @@ class TestShare(GuiBaseTest): ), ) - tmp_file = tempfile.NamedTemporaryFile() - with open(tmp_file.name, "wb") as f: - f.write(r.content) + tmp_file = tempfile.NamedTemporaryFile("wb") + tmp_file.write(r.content) with open(tmp_file.name, "r") as f: self.assertEqual("onionshare", f.read()) @@ -207,7 +206,10 @@ class TestShare(GuiBaseTest): QtTest.QTest.mouseRelease( tab.get_mode().server_status.server_button, QtCore.Qt.LeftButton ) - self.assertEqual(tab.get_mode().server_status.status, 0) + self.assertEqual( + tab.get_mode().server_status.status, + tab.get_mode().server_status.STATUS_STOPPED, + ) self.server_is_stopped(tab) self.web_server_is_stopped(tab) From cf61f3ba43b1cc6b2fdb88e891e081333f211989 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 21 Aug 2020 18:34:14 -0400 Subject: [PATCH 09/17] Windows batch script for running tests --- tests/run.bat | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 tests/run.bat diff --git a/tests/run.bat b/tests/run.bat new file mode 100644 index 00000000..5db3f14a --- /dev/null +++ b/tests/run.bat @@ -0,0 +1,9 @@ +pytest -vvv tests\test_cli.py +pytest -vvv tests\test_cli_common.py +pytest -vvv tests\test_cli_settings.py +pytest -vvv tests\test_cli_strings.py +pytest -vvv tests\test_cli_web.py +pytest -vvv --rungui tests\test_gui_tabs.py +pytest -vvv --rungui tests\test_gui_share.py +pytest -vvv --rungui tests\test_gui_receive.py +pytest -vvv --rungui tests\test_gui_website.py From f55588c08c20da6a2901c7f4cb4f1dd664b38849 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 21 Aug 2020 18:37:15 -0400 Subject: [PATCH 10/17] In web tests, allow mime-type to be either application/zip or application/x-zip-compressed --- tests/test_cli_web.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tests/test_cli_web.py b/tests/test_cli_web.py index 2e7d427b..6c2e14a3 100644 --- a/tests/test_cli_web.py +++ b/tests/test_cli_web.py @@ -93,7 +93,10 @@ class TestWeb: res = c.get("/download", headers=self._make_auth_headers(web.password)) res.get_data() assert res.status_code == 200 - assert res.mimetype == "application/zip" + assert ( + res.mimetype == "application/zip" + or res.mimetype == "application/x-zip-compressed" + ) def test_share_mode_autostop_sharing_on(self, temp_dir, common_obj, temp_file_1024): web = web_obj(temp_dir, common_obj, "share", 3) @@ -106,11 +109,16 @@ class TestWeb: res = c.get("/download", headers=self._make_auth_headers(web.password)) res.get_data() assert res.status_code == 200 - assert res.mimetype == "application/zip" + assert ( + res.mimetype == "application/zip" + or res.mimetype == "application/x-zip-compressed" + ) assert web.running == False - def test_share_mode_autostop_sharing_off(self, temp_dir, common_obj, temp_file_1024): + def test_share_mode_autostop_sharing_off( + self, temp_dir, common_obj, temp_file_1024 + ): web = web_obj(temp_dir, common_obj, "share", 3) web.settings.set("share", "autostop_sharing", False) @@ -121,7 +129,10 @@ class TestWeb: res = c.get("/download", headers=self._make_auth_headers(web.password)) res.get_data() assert res.status_code == 200 - assert res.mimetype == "application/zip" + assert ( + res.mimetype == "application/zip" + or res.mimetype == "application/x-zip-compressed" + ) assert web.running == True def test_receive_mode(self, temp_dir, common_obj): From 0b962d18efae8747d2d6eb09b0ced3c2cd910322 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 21 Aug 2020 19:14:40 -0400 Subject: [PATCH 11/17] When stopping an onion, dont even try if --local-only --- onionshare/onion.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/onionshare/onion.py b/onionshare/onion.py index 88d72496..23286635 100644 --- a/onionshare/onion.py +++ b/onionshare/onion.py @@ -665,15 +665,16 @@ class Onion(object): Stop a specific onion service """ onion_host = mode_settings.get("general", "service_id") - self.common.log("Onion", "stop_onion_service", f"onion host: {onion_host}") - try: - self.c.remove_ephemeral_hidden_service( - mode_settings.get("general", "service_id") - ) - except: - self.common.log( - "Onion", "stop_onion_service", f"failed to remove {onion_host}" - ) + if onion_host: + self.common.log("Onion", "stop_onion_service", f"onion host: {onion_host}") + try: + self.c.remove_ephemeral_hidden_service( + mode_settings.get("general", "service_id") + ) + except: + self.common.log( + "Onion", "stop_onion_service", f"failed to remove {onion_host}" + ) def cleanup(self, stop_tor=True): """ From 283554a655da9ae9859ccc25903ede90a215bce2 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 21 Aug 2020 19:14:53 -0400 Subject: [PATCH 12/17] Wait longer, and Windows tests work --- tests/test_gui_share.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_gui_share.py b/tests/test_gui_share.py index 58c90977..414472c0 100644 --- a/tests/test_gui_share.py +++ b/tests/test_gui_share.py @@ -199,6 +199,7 @@ class TestShare(GuiBaseTest): self.add_remove_buttons_hidden(tab) self.mode_settings_widget_is_hidden(tab) self.set_autostart_timer(tab, 10) + QtTest.QTest.qWait(500) QtTest.QTest.mousePress( tab.get_mode().server_status.server_button, QtCore.Qt.LeftButton ) @@ -206,6 +207,7 @@ class TestShare(GuiBaseTest): QtTest.QTest.mouseRelease( tab.get_mode().server_status.server_button, QtCore.Qt.LeftButton ) + QtTest.QTest.qWait(500) self.assertEqual( tab.get_mode().server_status.status, tab.get_mode().server_status.STATUS_STOPPED, From 15f7d196708f71c862298999cb61e16333ce8c02 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 21 Aug 2020 19:21:06 -0400 Subject: [PATCH 13/17] Fix one more tempfile Windows test bug --- tests/test_gui_share.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_gui_share.py b/tests/test_gui_share.py index 414472c0..441fc03a 100644 --- a/tests/test_gui_share.py +++ b/tests/test_gui_share.py @@ -135,11 +135,13 @@ class TestShare(GuiBaseTest): ), ) - tmp_file = tempfile.NamedTemporaryFile("wb") + tmp_file = tempfile.NamedTemporaryFile("wb", delete=False) tmp_file.write(r.content) + tmp_file.close() with open(tmp_file.name, "r") as f: self.assertEqual("onionshare", f.read()) + os.remove(tmp_file.name) QtTest.QTest.qWait(500) From 9b78f23ca32feebeec4c866e6a53cd6535c0ebd9 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 21 Aug 2020 19:34:00 -0400 Subject: [PATCH 14/17] Skip receive mode file permission tests in Windows --- tests/test_gui_receive.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_gui_receive.py b/tests/test_gui_receive.py index bd9cf491..d9501460 100644 --- a/tests/test_gui_receive.py +++ b/tests/test_gui_receive.py @@ -2,6 +2,7 @@ import pytest import os import requests import shutil +import sys from datetime import datetime, timedelta from PyQt5 import QtCore, QtTest @@ -213,6 +214,7 @@ class TestReceive(GuiBaseTest): self.close_all_tabs() @pytest.mark.gui + @pytest.mark.skipif(sys.platform == "win32", reason="Windows doesn't have chmod") def test_upload_non_writable_dir(self): """ Test uploading files to a non-writable directory @@ -237,6 +239,7 @@ class TestReceive(GuiBaseTest): self.close_all_tabs() @pytest.mark.gui + @pytest.mark.skipif(sys.platform == "win32", reason="Windows doesn't have chmod") def test_public_upload_non_writable_dir(self): """ Test uploading files to a non-writable directory in public mode From 24b7316b3ea437c60638910f4badd4f2fef2071e Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 21 Aug 2020 19:41:29 -0400 Subject: [PATCH 15/17] Updated build instructions for running tests --- BUILD.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/BUILD.md b/BUILD.md index f85b22d1..16c7395d 100644 --- a/BUILD.md +++ b/BUILD.md @@ -264,6 +264,8 @@ This will prompt you to codesign three binaries and execute one unsigned binary. # Running tests +## Tests in macOS and Linux + OnionShare includes PyTest unit tests. To run tests, you can run `pytest` against the `tests/` directory. ```sh @@ -276,20 +278,20 @@ You can run GUI tests like this: poetry run ./tests/run.sh --rungui ``` -If you would like to also run the GUI unit tests in 'tor' mode, start Tor Browser in the background, then run: - -```sh -poetry run ./tests/run.sh --rungui --runtor -``` - -Keep in mind that the Tor tests take a lot longer to run than local mode, but they are also more comprehensive. - -You can also choose to wrap the tests in `xvfb-run` so that a ton of OnionShare windows don't pop up on your desktop (you may need to install the `xorg-x11-server-Xvfb` package), like this: +If you're using Linux, you can also choose to wrap the tests in `xvfb-run` so that a ton of OnionShare windows don't pop up on your desktop (you may need to install the `xorg-x11-server-Xvfb` package), like this: ```sh xvfb-run poetry run ./tests/run.sh --rungui ``` +## Tests in Windows + +You can run this Windows batch script to run all of the CLI and GUI tests. + +``` +poetry run tests\run.bat +``` + # Making releases This section documents the release process. Unless you're a core OnionShare developer making a release, you'll probably never need to follow it. From a105ce722919997f142f431a5679061ace801880 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 21 Aug 2020 19:44:02 -0400 Subject: [PATCH 16/17] Use Qt 5.14.0 in macOS --- BUILD.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD.md b/BUILD.md index 16c7395d..8b51f150 100644 --- a/BUILD.md +++ b/BUILD.md @@ -115,7 +115,7 @@ Download and install Python 3.7.4 from https://www.python.org/downloads/release/ You may also need to run the command `/Applications/Python\ 3.7/Install\ Certificates.command` to update Python 3.6's internal certificate store. Otherwise, you may find that fetching the Tor Browser .dmg file fails later due to a certificate validation error. -Install Qt 5.13.1 for macOS from https://www.qt.io/offline-installers. I downloaded `qt-opensource-mac-x64-5.13.1.dmg`. In the installer, you can skip making an account, and all you need is `Qt` > `Qt 5.13.1` > `macOS`. +Install Qt 5.14.0 for macOS from https://www.qt.io/offline-installers. I downloaded `qt-opensource-mac-x64-5.14.0.dmg`. In the installer, you can skip making an account, and all you need is `Qt` > `Qt 5.14.0` > `macOS`. If you don't have it already, install poetry (`pip3 install --user poetry`). Then install dependencies: From 6b53e3f2c52d346de8a51d20b87ce04dc9a125c4 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Thu, 27 Aug 2020 17:59:00 -0400 Subject: [PATCH 17/17] Wait longer in GUI tabs test, and check for the precense of chat mode widget in GUI base tests --- tests/gui_base_test.py | 1 + tests/test_gui_tabs.py | 14 ++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/gui_base_test.py b/tests/gui_base_test.py index 0d2d4fa1..2b9bcd99 100644 --- a/tests/gui_base_test.py +++ b/tests/gui_base_test.py @@ -87,6 +87,7 @@ class GuiBaseTest(unittest.TestCase): self.assertFalse(hasattr(tab, "share_mode")) self.assertFalse(hasattr(tab, "receive_mode")) self.assertFalse(hasattr(tab, "website_mode")) + self.assertFalse(hasattr(tab, "chat_mode")) def new_share_tab(self): tab = self.gui.tabs.widget(0) diff --git a/tests/test_gui_tabs.py b/tests/test_gui_tabs.py index eda30f79..a2473441 100644 --- a/tests/test_gui_tabs.py +++ b/tests/test_gui_tabs.py @@ -20,7 +20,7 @@ class TestTabs(GuiBaseTest): tab.get_mode().server_status.status, tab.get_mode().server_status.STATUS_WORKING, ) - QtTest.QTest.qWait(500) + QtTest.QTest.qWait(1000) self.assertEqual( tab.get_mode().server_status.status, tab.get_mode().server_status.STATUS_STARTED, @@ -138,21 +138,27 @@ class TestTabs(GuiBaseTest): self.gui.tabs.widget(1).share_button.click() self.assertFalse(self.gui.tabs.widget(1).new_tab.isVisible()) self.assertTrue(self.gui.tabs.widget(1).share_mode.isVisible()) - self.assertEqual(self.gui.status_bar.server_status_label.text(), 'Ready to share') + self.assertEqual( + self.gui.status_bar.server_status_label.text(), "Ready to share" + ) # New tab, receive files self.gui.tabs.new_tab_button.click() self.gui.tabs.widget(2).receive_button.click() self.assertFalse(self.gui.tabs.widget(2).new_tab.isVisible()) self.assertTrue(self.gui.tabs.widget(2).receive_mode.isVisible()) - self.assertEqual(self.gui.status_bar.server_status_label.text(), 'Ready to receive') + self.assertEqual( + self.gui.status_bar.server_status_label.text(), "Ready to receive" + ) # New tab, publish website self.gui.tabs.new_tab_button.click() self.gui.tabs.widget(3).website_button.click() self.assertFalse(self.gui.tabs.widget(3).new_tab.isVisible()) self.assertTrue(self.gui.tabs.widget(3).website_mode.isVisible()) - self.assertEqual(self.gui.status_bar.server_status_label.text(), 'Ready to share') + self.assertEqual( + self.gui.status_bar.server_status_label.text(), "Ready to share" + ) # Close tabs self.gui.tabs.tabBar().tabButton(0, QtWidgets.QTabBar.RightSide).click()