diff options
author | Miguel Jacq <mig@mig5.net> | 2018-11-13 14:45:40 +1100 |
---|---|---|
committer | Miguel Jacq <mig@mig5.net> | 2018-11-13 14:45:40 +1100 |
commit | d3b5e1e256e7b122e33b98f79bf498408e1233db (patch) | |
tree | 5ac985a9da2638256b4061a90559a17e9b1dd631 /tests | |
parent | db8548c35bd5d0236c3083e9e860b82a1dbca808 (diff) | |
parent | a39cd08083f4443e498611bbc1c086a05f5cffde (diff) | |
download | onionshare-d3b5e1e256e7b122e33b98f79bf498408e1233db.tar.gz onionshare-d3b5e1e256e7b122e33b98f79bf498408e1233db.zip |
Merge develop branch and fix conflicts
Diffstat (limited to 'tests')
41 files changed, 1963 insertions, 12 deletions
diff --git a/tests/GuiBaseTest.py b/tests/GuiBaseTest.py new file mode 100644 index 00000000..c557fc15 --- /dev/null +++ b/tests/GuiBaseTest.py @@ -0,0 +1,323 @@ +import json +import os +import requests +import shutil +import socket +import socks + +from PyQt5 import QtCore, QtTest + +from onionshare import strings +from onionshare.common import Common +from onionshare.settings import Settings +from onionshare.onion import Onion +from onionshare.web import Web +from onionshare_gui import Application, OnionShare, OnionShareGui +from onionshare_gui.mode.share_mode import ShareMode +from onionshare_gui.mode.receive_mode import ReceiveMode + + +class GuiBaseTest(object): + @staticmethod + def set_up(test_settings): + '''Create GUI with given settings''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + + # Create a test dir and files + if not os.path.exists('/tmp/testdir'): + testdir = os.mkdir('/tmp/testdir') + testfile = open('/tmp/testdir/test', 'w') + testfile.write('onionshare') + testfile.close() + + common = Common() + common.settings = Settings(common) + common.define_css() + strings.load_strings(common) + + # Get all of the settings in test_settings + test_settings['downloads_dir'] = '/tmp/OnionShare' + for key, val in common.settings.default_settings.items(): + if key not in test_settings: + test_settings[key] = val + + # Start the Onion + testonion = Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, True, 0) + + web = Web(common, False, True) + open('/tmp/settings.json', 'w').write(json.dumps(test_settings)) + + gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt', '/tmp/testdir'], '/tmp/settings.json', True) + return gui + + @staticmethod + def tear_down(): + '''Clean up after tests''' + try: + os.remove('/tmp/test.txt') + os.remove('/tmp/settings.json') + os.remove('/tmp/large_file') + os.remove('/tmp/download.zip') + os.remove('/tmp/webpage') + shutil.rmtree('/tmp/testdir') + shutil.rmtree('/tmp/OnionShare') + except: + pass + + + def gui_loaded(self): + '''Test that the GUI actually is shown''' + self.assertTrue(self.gui.show) + + + def windowTitle_seen(self): + '''Test that the window title is OnionShare''' + self.assertEqual(self.gui.windowTitle(), 'OnionShare') + + + def settings_button_is_visible(self): + '''Test that the settings button is visible''' + self.assertTrue(self.gui.settings_button.isVisible()) + + + def settings_button_is_hidden(self): + '''Test that the settings button is hidden when the server starts''' + self.assertFalse(self.gui.settings_button.isVisible()) + + + def server_status_bar_is_visible(self): + '''Test that the status bar is visible''' + self.assertTrue(self.gui.status_bar.isVisible()) + + + def click_mode(self, mode): + '''Test that we can switch Mode by clicking the button''' + if type(mode) == ReceiveMode: + QtTest.QTest.mouseClick(self.gui.receive_mode_button, QtCore.Qt.LeftButton) + self.assertTrue(self.gui.mode, self.gui.MODE_RECEIVE) + if type(mode) == ShareMode: + QtTest.QTest.mouseClick(self.gui.share_mode_button, QtCore.Qt.LeftButton) + self.assertTrue(self.gui.mode, self.gui.MODE_SHARE) + + + def click_toggle_history(self, mode): + '''Test that we can toggle Download or Upload history by clicking the toggle button''' + currently_visible = mode.history.isVisible() + QtTest.QTest.mouseClick(mode.toggle_history, QtCore.Qt.LeftButton) + self.assertEqual(mode.history.isVisible(), not currently_visible) + + + def history_indicator(self, mode, public_mode): + '''Test that we can make sure the history is toggled off, do an action, and the indiciator works''' + # Make sure history is toggled off + if mode.history.isVisible(): + QtTest.QTest.mouseClick(mode.toggle_history, QtCore.Qt.LeftButton) + self.assertFalse(mode.history.isVisible()) + + # Indicator should not be visible yet + self.assertFalse(mode.toggle_history.indicator_label.isVisible()) + + if type(mode) == ReceiveMode: + # Upload a file + files = {'file[]': open('/tmp/test.txt', 'rb')} + if not public_mode: + path = 'http://127.0.0.1:{}/{}/upload'.format(self.gui.app.port, mode.web.slug) + else: + path = 'http://127.0.0.1:{}/upload'.format(self.gui.app.port) + response = requests.post(path, files=files) + QtTest.QTest.qWait(2000) + + if type(mode) == ShareMode: + # Download files + if public_mode: + url = "http://127.0.0.1:{}/download".format(self.gui.app.port) + else: + url = "http://127.0.0.1:{}/{}/download".format(self.gui.app.port, mode.web.slug) + r = requests.get(url) + QtTest.QTest.qWait(2000) + + # Indicator should be visible, have a value of "1" + self.assertTrue(mode.toggle_history.indicator_label.isVisible()) + self.assertEqual(mode.toggle_history.indicator_label.text(), "1") + + # Toggle history back on, indicator should be hidden again + QtTest.QTest.mouseClick(mode.toggle_history, QtCore.Qt.LeftButton) + self.assertFalse(mode.toggle_history.indicator_label.isVisible()) + + + def history_is_not_visible(self, mode): + '''Test that the History section is not visible''' + self.assertFalse(mode.history.isVisible()) + + + def history_is_visible(self, mode): + '''Test that the History section is visible''' + self.assertTrue(mode.history.isVisible()) + + + def server_working_on_start_button_pressed(self, mode): + '''Test we can start the service''' + # Should be in SERVER_WORKING state + QtTest.QTest.mouseClick(mode.server_status.server_button, QtCore.Qt.LeftButton) + self.assertEqual(mode.server_status.status, 1) + + + def server_status_indicator_says_starting(self, mode): + '''Test that the Server Status indicator shows we are Starting''' + self.assertEqual(mode.server_status_label.text(), strings._('gui_status_indicator_share_working')) + + + def server_is_started(self, mode, startup_time=2000): + '''Test that the server has started''' + QtTest.QTest.qWait(startup_time) + # Should now be in SERVER_STARTED state + self.assertEqual(mode.server_status.status, 2) + + + def web_server_is_running(self): + '''Test that the web server has started''' + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + + self.assertEqual(sock.connect_ex(('127.0.0.1',self.gui.app.port)), 0) + + + def have_a_slug(self, mode, public_mode): + '''Test that we have a valid slug''' + if not public_mode: + self.assertRegex(mode.server_status.web.slug, r'(\w+)-(\w+)') + else: + self.assertIsNone(mode.server_status.web.slug, r'(\w+)-(\w+)') + + + def url_description_shown(self, mode): + '''Test that the URL label is showing''' + self.assertTrue(mode.server_status.url_description.isVisible()) + + + def have_copy_url_button(self, mode, public_mode): + '''Test that the Copy URL button is shown and that the clipboard is correct''' + self.assertTrue(mode.server_status.copy_url_button.isVisible()) + + QtTest.QTest.mouseClick(mode.server_status.copy_url_button, QtCore.Qt.LeftButton) + clipboard = self.gui.qtapp.clipboard() + if public_mode: + self.assertEqual(clipboard.text(), 'http://127.0.0.1:{}'.format(self.gui.app.port)) + else: + self.assertEqual(clipboard.text(), 'http://127.0.0.1:{}/{}'.format(self.gui.app.port, mode.server_status.web.slug)) + + + def server_status_indicator_says_started(self, mode): + '''Test that the Server Status indicator shows we are started''' + if type(mode) == ReceiveMode: + self.assertEqual(mode.server_status_label.text(), strings._('gui_status_indicator_receive_started')) + if type(mode) == ShareMode: + self.assertEqual(mode.server_status_label.text(), strings._('gui_status_indicator_share_started')) + + + def web_page(self, mode, string, public_mode): + '''Test that the web page contains a string''' + s = socks.socksocket() + s.settimeout(60) + s.connect(('127.0.0.1', self.gui.app.port)) + + if not public_mode: + path = '/{}'.format(mode.server_status.web.slug) + else: + path = '/' + + http_request = 'GET {} HTTP/1.0\r\n'.format(path) + http_request += 'Host: 127.0.0.1\r\n' + http_request += '\r\n' + s.sendall(http_request.encode('utf-8')) + + with open('/tmp/webpage', 'wb') as file_to_write: + while True: + data = s.recv(1024) + if not data: + break + file_to_write.write(data) + file_to_write.close() + + f = open('/tmp/webpage') + self.assertTrue(string in f.read()) + f.close() + + + def history_widgets_present(self, mode): + '''Test that the relevant widgets are present in the history view after activity has taken place''' + self.assertFalse(mode.history.empty.isVisible()) + self.assertTrue(mode.history.not_empty.isVisible()) + + + def counter_incremented(self, mode, count): + '''Test that the counter has incremented''' + self.assertEqual(mode.history.completed_count, count) + + + def server_is_stopped(self, mode, stay_open): + '''Test that the server stops when we click Stop''' + if type(mode) == ReceiveMode or (type(mode) == ShareMode and stay_open): + QtTest.QTest.mouseClick(mode.server_status.server_button, QtCore.Qt.LeftButton) + self.assertEqual(mode.server_status.status, 0) + + + def web_server_is_stopped(self): + '''Test that the web server also stopped''' + QtTest.QTest.qWait(2000) + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + + # We should be closed by now. Fail if not! + self.assertNotEqual(sock.connect_ex(('127.0.0.1',self.gui.app.port)), 0) + + + def server_status_indicator_says_closed(self, mode, stay_open): + '''Test that the Server Status indicator shows we closed''' + if type(mode) == ReceiveMode: + self.assertEqual(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_receive_stopped')) + if type(mode) == ShareMode: + if stay_open: + self.assertEqual(self.gui.share_mode.server_status_label.text(), strings._('gui_status_indicator_share_stopped')) + else: + self.assertEqual(self.gui.share_mode.server_status_label.text(), strings._('closing_automatically')) + + + # Auto-stop timer tests + def set_timeout(self, mode, timeout): + '''Test that the timeout can be set''' + timer = QtCore.QDateTime.currentDateTime().addSecs(timeout) + mode.server_status.shutdown_timeout.setDateTime(timer) + self.assertTrue(mode.server_status.shutdown_timeout.dateTime(), timer) + + + def timeout_widget_hidden(self, mode): + '''Test that the timeout widget is hidden when share has started''' + self.assertFalse(mode.server_status.shutdown_timeout_container.isVisible()) + + + def server_timed_out(self, mode, wait): + '''Test that the server has timed out after the timer ran out''' + QtTest.QTest.qWait(wait) + # We should have timed out now + self.assertEqual(mode.server_status.status, 0) + + # Hack to close an Alert dialog that would otherwise block tests + def accept_dialog(self): + window = self.gui.qtapp.activeWindow() + if window: + window.close() + + # 'Grouped' tests follow from here + + def run_all_common_setup_tests(self): + self.gui_loaded() + self.windowTitle_seen() + self.settings_button_is_visible() + self.server_status_bar_is_visible() + + diff --git a/tests/GuiReceiveTest.py b/tests/GuiReceiveTest.py new file mode 100644 index 00000000..eaed8343 --- /dev/null +++ b/tests/GuiReceiveTest.py @@ -0,0 +1,124 @@ +import os +import requests +from datetime import datetime, timedelta +from PyQt5 import QtCore, QtTest +from .GuiBaseTest import GuiBaseTest + +class GuiReceiveTest(GuiBaseTest): + def upload_file(self, public_mode, file_to_upload, expected_basename): + '''Test that we can upload the file''' + files = {'file[]': open(file_to_upload, 'rb')} + if not public_mode: + path = 'http://127.0.0.1:{}/{}/upload'.format(self.gui.app.port, self.gui.receive_mode.web.slug) + else: + path = 'http://127.0.0.1:{}/upload'.format(self.gui.app.port) + response = requests.post(path, files=files) + QtTest.QTest.qWait(2000) + + # Make sure the file is within the last 10 seconds worth of filenames + exists = False + now = datetime.now() + for i in range(10): + date_dir = now.strftime("%Y-%m-%d") + time_dir = now.strftime("%H.%M.%S") + receive_mode_dir = os.path.join(self.gui.common.settings.get('downloads_dir'), date_dir, time_dir) + expected_filename = os.path.join(receive_mode_dir, expected_basename) + if os.path.exists(expected_filename): + exists = True + break + now = now - timedelta(seconds=1) + + self.assertTrue(exists) + + def upload_file_should_fail(self, public_mode): + '''Test that we can't upload the file when permissions are wrong, and expected content is shown''' + files = {'file[]': open('/tmp/test.txt', 'rb')} + if not public_mode: + path = 'http://127.0.0.1:{}/{}/upload'.format(self.gui.app.port, self.gui.receive_mode.web.slug) + else: + path = 'http://127.0.0.1:{}/upload'.format(self.gui.app.port) + response = requests.post(path, files=files) + + QtCore.QTimer.singleShot(1000, self.accept_dialog) + self.assertTrue('Error uploading, please inform the OnionShare user' in response.text) + + def upload_dir_permissions(self, mode=0o755): + '''Manipulate the permissions on the upload dir in between tests''' + os.chmod('/tmp/OnionShare', mode) + + def try_public_paths_in_non_public_mode(self): + response = requests.post('http://127.0.0.1:{}/upload'.format(self.gui.app.port)) + self.assertEqual(response.status_code, 404) + response = requests.get('http://127.0.0.1:{}/close'.format(self.gui.app.port)) + self.assertEqual(response.status_code, 404) + + def run_receive_mode_sender_closed_tests(self, public_mode): + '''Test that the share can be stopped by the sender in receive mode''' + if not public_mode: + path = 'http://127.0.0.1:{}/{}/close'.format(self.gui.app.port, self.gui.receive_mode.web.slug) + else: + path = 'http://127.0.0.1:{}/close'.format(self.gui.app.port) + response = requests.post(path) + self.server_is_stopped(self.gui.receive_mode, False) + self.web_server_is_stopped() + self.server_status_indicator_says_closed(self.gui.receive_mode, False) + + + # 'Grouped' tests follow from here + + def run_all_receive_mode_setup_tests(self, public_mode): + '''Set up a share in Receive mode and start it''' + self.click_mode(self.gui.receive_mode) + self.history_is_not_visible(self.gui.receive_mode) + self.click_toggle_history(self.gui.receive_mode) + self.history_is_visible(self.gui.receive_mode) + self.server_working_on_start_button_pressed(self.gui.receive_mode) + self.server_status_indicator_says_starting(self.gui.receive_mode) + self.settings_button_is_hidden() + self.server_is_started(self.gui.receive_mode) + self.web_server_is_running() + self.have_a_slug(self.gui.receive_mode, public_mode) + self.url_description_shown(self.gui.receive_mode) + self.have_copy_url_button(self.gui.receive_mode, public_mode) + self.server_status_indicator_says_started(self.gui.receive_mode) + self.web_page(self.gui.receive_mode, 'Select the files you want to send, then click', public_mode) + + def run_all_receive_mode_tests(self, public_mode, receive_allow_receiver_shutdown): + '''Upload files in receive mode and stop the share''' + self.run_all_receive_mode_setup_tests(public_mode) + if not public_mode: + self.try_public_paths_in_non_public_mode() + self.upload_file(public_mode, '/tmp/test.txt', 'test.txt') + self.history_widgets_present(self.gui.receive_mode) + self.counter_incremented(self.gui.receive_mode, 1) + self.upload_file(public_mode, '/tmp/test.txt', 'test.txt') + self.counter_incremented(self.gui.receive_mode, 2) + self.upload_file(public_mode, '/tmp/testdir/test', 'test') + self.counter_incremented(self.gui.receive_mode, 3) + self.upload_file(public_mode, '/tmp/testdir/test', 'test') + self.counter_incremented(self.gui.receive_mode, 4) + self.history_indicator(self.gui.receive_mode, public_mode) + self.server_is_stopped(self.gui.receive_mode, False) + self.web_server_is_stopped() + self.server_status_indicator_says_closed(self.gui.receive_mode, False) + self.server_working_on_start_button_pressed(self.gui.receive_mode) + self.server_is_started(self.gui.receive_mode) + self.history_indicator(self.gui.receive_mode, public_mode) + + def run_all_receive_mode_unwritable_dir_tests(self, public_mode, receive_allow_receiver_shutdown): + '''Attempt to upload (unwritable) files in receive mode and stop the share''' + self.run_all_receive_mode_setup_tests(public_mode) + self.upload_dir_permissions(0o400) + self.upload_file_should_fail(public_mode) + self.server_is_stopped(self.gui.receive_mode, True) + self.web_server_is_stopped() + self.server_status_indicator_says_closed(self.gui.receive_mode, False) + self.upload_dir_permissions(0o755) + + def run_all_receive_mode_timer_tests(self, public_mode): + """Auto-stop timer tests in receive mode""" + self.run_all_receive_mode_setup_tests(public_mode) + self.set_timeout(self.gui.receive_mode, 5) + self.timeout_widget_hidden(self.gui.receive_mode) + self.server_timed_out(self.gui.receive_mode, 15000) + self.web_server_is_stopped() diff --git a/tests/GuiShareTest.py b/tests/GuiShareTest.py new file mode 100644 index 00000000..716bab73 --- /dev/null +++ b/tests/GuiShareTest.py @@ -0,0 +1,204 @@ +import os +import requests +import socks +import zipfile +from PyQt5 import QtCore, QtTest +from .GuiBaseTest import GuiBaseTest + +class GuiShareTest(GuiBaseTest): + # Persistence tests + def have_same_slug(self, slug): + '''Test that we have the same slug''' + self.assertEqual(self.gui.share_mode.server_status.web.slug, slug) + + # Share-specific tests + + def file_selection_widget_has_files(self, num=2): + '''Test that the number of items in the list is as expected''' + self.assertEqual(self.gui.share_mode.server_status.file_selection.get_num_files(), num) + + + def deleting_all_files_hides_delete_button(self): + '''Test that clicking on the file item shows the delete button. Test that deleting the only item in the list hides the delete button''' + rect = self.gui.share_mode.server_status.file_selection.file_list.visualItemRect(self.gui.share_mode.server_status.file_selection.file_list.item(0)) + QtTest.QTest.mouseClick(self.gui.share_mode.server_status.file_selection.file_list.viewport(), QtCore.Qt.LeftButton, pos=rect.center()) + # Delete button should be visible + self.assertTrue(self.gui.share_mode.server_status.file_selection.delete_button.isVisible()) + # Click delete, delete button should still be visible since we have one more file + QtTest.QTest.mouseClick(self.gui.share_mode.server_status.file_selection.delete_button, QtCore.Qt.LeftButton) + + rect = self.gui.share_mode.server_status.file_selection.file_list.visualItemRect(self.gui.share_mode.server_status.file_selection.file_list.item(0)) + QtTest.QTest.mouseClick(self.gui.share_mode.server_status.file_selection.file_list.viewport(), QtCore.Qt.LeftButton, pos=rect.center()) + self.assertTrue(self.gui.share_mode.server_status.file_selection.delete_button.isVisible()) + QtTest.QTest.mouseClick(self.gui.share_mode.server_status.file_selection.delete_button, QtCore.Qt.LeftButton) + + # No more files, the delete button should be hidden + self.assertFalse(self.gui.share_mode.server_status.file_selection.delete_button.isVisible()) + + + def add_a_file_and_delete_using_its_delete_widget(self): + '''Test that we can also delete a file by clicking on its [X] widget''' + self.gui.share_mode.server_status.file_selection.file_list.add_file('/etc/hosts') + QtTest.QTest.mouseClick(self.gui.share_mode.server_status.file_selection.file_list.item(0).item_button, QtCore.Qt.LeftButton) + self.file_selection_widget_has_files(0) + + + def file_selection_widget_readd_files(self): + '''Re-add some files to the list so we can share''' + self.gui.share_mode.server_status.file_selection.file_list.add_file('/etc/hosts') + self.gui.share_mode.server_status.file_selection.file_list.add_file('/tmp/test.txt') + self.file_selection_widget_has_files(2) + + + def add_large_file(self): + '''Add a large file to the share''' + size = 1024*1024*155 + with open('/tmp/large_file', 'wb') as fout: + fout.write(os.urandom(size)) + self.gui.share_mode.server_status.file_selection.file_list.add_file('/tmp/large_file') + + + def add_delete_buttons_hidden(self): + '''Test that the add and delete buttons are hidden when the server starts''' + self.assertFalse(self.gui.share_mode.server_status.file_selection.add_button.isVisible()) + self.assertFalse(self.gui.share_mode.server_status.file_selection.delete_button.isVisible()) + + + def download_share(self, public_mode): + '''Test that we can download the share''' + s = socks.socksocket() + s.settimeout(60) + s.connect(('127.0.0.1', self.gui.app.port)) + + if public_mode: + path = '/download' + else: + path = '{}/download'.format(self.gui.share_mode.web.slug) + + http_request = 'GET {} HTTP/1.0\r\n'.format(path) + http_request += 'Host: 127.0.0.1\r\n' + http_request += '\r\n' + s.sendall(http_request.encode('utf-8')) + + with open('/tmp/download.zip', 'wb') as file_to_write: + while True: + data = s.recv(1024) + if not data: + break + file_to_write.write(data) + file_to_write.close() + + zip = zipfile.ZipFile('/tmp/download.zip') + QtTest.QTest.qWait(2000) + self.assertEqual('onionshare', zip.read('test.txt').decode('utf-8')) + + def hit_404(self, public_mode): + '''Test that the server stops after too many 404s, or doesn't when in public_mode''' + bogus_path = '/gimme' + url = "http://127.0.0.1:{}/{}".format(self.gui.app.port, bogus_path) + + for _ in range(20): + r = requests.get(url) + + # A nasty hack to avoid the Alert dialog that blocks the rest of the test + if not public_mode: + QtCore.QTimer.singleShot(1000, self.accept_dialog) + + # In public mode, we should still be running (no rate-limiting) + if public_mode: + self.web_server_is_running() + # In non-public mode, we should be shut down (rate-limiting) + else: + self.web_server_is_stopped() + + + def add_button_visible(self): + '''Test that the add button should be visible''' + self.assertTrue(self.gui.share_mode.server_status.file_selection.add_button.isVisible()) + + + # 'Grouped' tests follow from here + + def run_all_share_mode_setup_tests(self): + """Tests in share mode prior to starting a share""" + self.click_mode(self.gui.share_mode) + self.file_selection_widget_has_files() + self.history_is_not_visible(self.gui.share_mode) + self.click_toggle_history(self.gui.share_mode) + self.history_is_visible(self.gui.share_mode) + self.deleting_all_files_hides_delete_button() + self.add_a_file_and_delete_using_its_delete_widget() + self.file_selection_widget_readd_files() + + + def run_all_share_mode_started_tests(self, public_mode, startup_time=2000): + """Tests in share mode after starting a share""" + self.server_working_on_start_button_pressed(self.gui.share_mode) + self.server_status_indicator_says_starting(self.gui.share_mode) + self.add_delete_buttons_hidden() + self.settings_button_is_hidden() + self.server_is_started(self.gui.share_mode, startup_time) + self.web_server_is_running() + self.have_a_slug(self.gui.share_mode, public_mode) + self.url_description_shown(self.gui.share_mode) + self.have_copy_url_button(self.gui.share_mode, public_mode) + self.server_status_indicator_says_started(self.gui.share_mode) + + + def run_all_share_mode_download_tests(self, public_mode, stay_open): + """Tests in share mode after downloading a share""" + self.web_page(self.gui.share_mode, 'Total size', public_mode) + self.download_share(public_mode) + self.history_widgets_present(self.gui.share_mode) + self.server_is_stopped(self.gui.share_mode, stay_open) + self.web_server_is_stopped() + self.server_status_indicator_says_closed(self.gui.share_mode, stay_open) + self.add_button_visible() + self.server_working_on_start_button_pressed(self.gui.share_mode) + self.server_is_started(self.gui.share_mode) + self.history_indicator(self.gui.share_mode, public_mode) + + + def run_all_share_mode_tests(self, public_mode, stay_open): + """End-to-end share tests""" + self.run_all_share_mode_setup_tests() + self.run_all_share_mode_started_tests(public_mode) + self.run_all_share_mode_download_tests(public_mode, stay_open) + + + def run_all_large_file_tests(self, public_mode, stay_open): + """Same as above but with a larger file""" + self.run_all_share_mode_setup_tests() + self.add_large_file() + self.run_all_share_mode_started_tests(public_mode, startup_time=15000) + self.assertTrue(self.gui.share_mode.filesize_warning.isVisible()) + self.server_is_stopped(self.gui.share_mode, stay_open) + self.web_server_is_stopped() + self.server_status_indicator_says_closed(self.gui.share_mode, stay_open) + + + def run_all_share_mode_persistent_tests(self, public_mode, stay_open): + """Same as end-to-end share tests but also test the slug is the same on multiple shared""" + self.run_all_share_mode_setup_tests() + self.run_all_share_mode_started_tests(public_mode) + slug = self.gui.share_mode.server_status.web.slug + self.run_all_share_mode_download_tests(public_mode, stay_open) + self.have_same_slug(slug) + + + def run_all_share_mode_timer_tests(self, public_mode): + """Auto-stop timer tests in share mode""" + self.run_all_share_mode_setup_tests() + self.set_timeout(self.gui.share_mode, 5) + self.run_all_share_mode_started_tests(public_mode) + self.timeout_widget_hidden(self.gui.share_mode) + self.server_timed_out(self.gui.share_mode, 10000) + self.web_server_is_stopped() + + + def run_all_share_mode_unreadable_file_tests(self): + '''Attempt to share an unreadable file''' + self.run_all_share_mode_setup_tests() + QtCore.QTimer.singleShot(1000, self.accept_dialog) + self.gui.share_mode.server_status.file_selection.file_list.add_file('/tmp/nonexistent.txt') + self.file_selection_widget_has_files(2) diff --git a/tests/SettingsGuiBaseTest.py b/tests/SettingsGuiBaseTest.py new file mode 100644 index 00000000..e59a58a8 --- /dev/null +++ b/tests/SettingsGuiBaseTest.py @@ -0,0 +1,44 @@ +import json +import os + +from onionshare import strings +from onionshare.common import Common +from onionshare.settings import Settings +from onionshare.onion import Onion +from onionshare_gui import Application, OnionShare +from onionshare_gui.settings_dialog import SettingsDialog + +class SettingsGuiBaseTest(object): + @staticmethod + def set_up(test_settings): + '''Create the GUI''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + + common = Common() + common.settings = Settings(common) + common.define_css() + strings.load_strings(common) + + # Start the Onion + testonion = Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, True, 0) + + for key, val in common.settings.default_settings.items(): + if key not in test_settings: + test_settings[key] = val + + open('/tmp/settings.json', 'w').write(json.dumps(test_settings)) + + gui = SettingsDialog(common, testonion, qtapp, '/tmp/settings.json', True) + return gui + + + @staticmethod + def tear_down(): + '''Clean up after tests''' + os.remove('/tmp/settings.json') diff --git a/tests/TorGuiBaseTest.py b/tests/TorGuiBaseTest.py new file mode 100644 index 00000000..9a0bda3e --- /dev/null +++ b/tests/TorGuiBaseTest.py @@ -0,0 +1,173 @@ +import json +import os +import requests +import socks + +from PyQt5 import QtCore, QtTest + +from onionshare import strings +from onionshare.common import Common +from onionshare.settings import Settings +from onionshare.onion import Onion +from onionshare.web import Web +from onionshare_gui import Application, OnionShare, OnionShareGui +from onionshare_gui.mode.share_mode import ShareMode +from onionshare_gui.mode.receive_mode import ReceiveMode + +from .GuiBaseTest import GuiBaseTest + +class TorGuiBaseTest(GuiBaseTest): + @staticmethod + def set_up(test_settings): + '''Create GUI with given settings''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + + # Create a test dir and files + if not os.path.exists('/tmp/testdir'): + testdir = os.mkdir('/tmp/testdir') + testfile = open('/tmp/testdir/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + + common = Common() + common.settings = Settings(common) + common.define_css() + strings.load_strings(common) + + # Get all of the settings in test_settings + test_settings['connection_type'] = 'automatic' + test_settings['downloads_dir'] = '/tmp/OnionShare' + for key, val in common.settings.default_settings.items(): + if key not in test_settings: + test_settings[key] = val + + # Start the Onion + testonion = Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, False, 0) + + web = Web(common, False, False) + open('/tmp/settings.json', 'w').write(json.dumps(test_settings)) + + gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt', '/tmp/testdir'], '/tmp/settings.json', False) + return gui + + def history_indicator(self, mode, public_mode): + '''Test that we can make sure the history is toggled off, do an action, and the indiciator works''' + # Make sure history is toggled off + if mode.history.isVisible(): + QtTest.QTest.mouseClick(mode.toggle_history, QtCore.Qt.LeftButton) + self.assertFalse(mode.history.isVisible()) + + # Indicator should not be visible yet + self.assertFalse(mode.toggle_history.indicator_label.isVisible()) + + # Set up connecting to the onion + (socks_address, socks_port) = self.gui.app.onion.get_tor_socks_port() + session = requests.session() + session.proxies = {} + session.proxies['http'] = 'socks5h://{}:{}'.format(socks_address, socks_port) + + if type(mode) == ReceiveMode: + # Upload a file + files = {'file[]': open('/tmp/test.txt', 'rb')} + if not public_mode: + path = 'http://{}/{}/upload'.format(self.gui.app.onion_host, mode.web.slug) + else: + path = 'http://{}/upload'.format(self.gui.app.onion_host) + response = session.post(path, files=files) + QtTest.QTest.qWait(4000) + + if type(mode) == ShareMode: + # Download files + if public_mode: + path = "http://{}/download".format(self.gui.app.onion_host) + else: + path = "http://{}/{}/download".format(self.gui.app.onion_host, mode.web.slug) + response = session.get(path) + QtTest.QTest.qWait(4000) + + # Indicator should be visible, have a value of "1" + self.assertTrue(mode.toggle_history.indicator_label.isVisible()) + self.assertEqual(mode.toggle_history.indicator_label.text(), "1") + + # Toggle history back on, indicator should be hidden again + QtTest.QTest.mouseClick(mode.toggle_history, QtCore.Qt.LeftButton) + self.assertFalse(mode.toggle_history.indicator_label.isVisible()) + + def have_an_onion_service(self): + '''Test that we have a valid Onion URL''' + self.assertRegex(self.gui.app.onion_host, r'[a-z2-7].onion') + + def web_page(self, mode, string, public_mode): + '''Test that the web page contains a string''' + (socks_address, socks_port) = self.gui.app.onion.get_tor_socks_port() + socks.set_default_proxy(socks.SOCKS5, socks_address, socks_port) + s = socks.socksocket() + s.settimeout(60) + s.connect((self.gui.app.onion_host, 80)) + if not public_mode: + path = '/{}'.format(mode.server_status.web.slug) + else: + path = '/' + http_request = 'GET {} HTTP/1.0\r\n'.format(path) + http_request += 'Host: {}\r\n'.format(self.gui.app.onion_host) + http_request += '\r\n' + s.sendall(http_request.encode('utf-8')) + with open('/tmp/webpage', 'wb') as file_to_write: + while True: + data = s.recv(1024) + if not data: + break + file_to_write.write(data) + file_to_write.close() + f = open('/tmp/webpage') + self.assertTrue(string in f.read()) + f.close() + + def have_copy_url_button(self, mode, public_mode): + '''Test that the Copy URL button is shown and that the clipboard is correct''' + self.assertTrue(mode.server_status.copy_url_button.isVisible()) + + QtTest.QTest.mouseClick(mode.server_status.copy_url_button, QtCore.Qt.LeftButton) + clipboard = self.gui.qtapp.clipboard() + if public_mode: + self.assertEqual(clipboard.text(), 'http://{}'.format(self.gui.app.onion_host)) + else: + self.assertEqual(clipboard.text(), 'http://{}/{}'.format(self.gui.app.onion_host, mode.server_status.web.slug)) + + def cancel_the_share(self, mode): + '''Test that we can cancel this share before it's started up ''' + self.server_working_on_start_button_pressed(self.gui.share_mode) + self.server_status_indicator_says_starting(self.gui.share_mode) + self.add_delete_buttons_hidden() + self.settings_button_is_hidden() + QtTest.QTest.mousePress(mode.server_status.server_button, QtCore.Qt.LeftButton) + QtTest.QTest.qWait(1000) + QtTest.QTest.mouseRelease(mode.server_status.server_button, QtCore.Qt.LeftButton) + self.assertEqual(mode.server_status.status, 0) + self.server_is_stopped(self.gui.share_mode, False) + self.web_server_is_stopped() + + + # Stealth tests + def copy_have_hidserv_auth_button(self, mode): + '''Test that the Copy HidservAuth button is shown''' + self.assertTrue(mode.server_status.copy_hidservauth_button.isVisible()) + + def hidserv_auth_string(self): + '''Test the validity of the HidservAuth string''' + self.assertRegex(self.gui.app.auth_string, r'HidServAuth {} [a-zA-Z1-9]'.format(self.gui.app.onion_host)) + + + + # Miscellaneous tests + def tor_killed_statusbar_message_shown(self, mode): + '''Test that the status bar message shows Tor was disconnected''' + self.gui.app.onion.c = None + QtTest.QTest.qWait(1000) + self.assertTrue(mode.status_bar.currentMessage(), strings._('gui_tor_connection_lost')) diff --git a/tests/TorGuiReceiveTest.py b/tests/TorGuiReceiveTest.py new file mode 100644 index 00000000..a21dd4fc --- /dev/null +++ b/tests/TorGuiReceiveTest.py @@ -0,0 +1,59 @@ +import os +import requests +from PyQt5 import QtTest +from .TorGuiBaseTest import TorGuiBaseTest + +class TorGuiReceiveTest(TorGuiBaseTest): + + def upload_file(self, public_mode, file_to_upload, expected_file): + '''Test that we can upload the file''' + (socks_address, socks_port) = self.gui.app.onion.get_tor_socks_port() + session = requests.session() + session.proxies = {} + session.proxies['http'] = 'socks5h://{}:{}'.format(socks_address, socks_port) + files = {'file[]': open(file_to_upload, 'rb')} + if not public_mode: + path = 'http://{}/{}/upload'.format(self.gui.app.onion_host, self.gui.receive_mode.web.slug) + else: + path = 'http://{}/upload'.format(self.gui.app.onion_host) + response = session.post(path, files=files) + QtTest.QTest.qWait(4000) + self.assertTrue(os.path.isfile(expected_file)) + + + # 'Grouped' tests follow from here + + def run_all_receive_mode_tests(self, public_mode, receive_allow_receiver_shutdown): + '''Run a full suite of tests in Receive mode''' + self.click_mode(self.gui.receive_mode) + self.history_is_not_visible(self.gui.receive_mode) + self.click_toggle_history(self.gui.receive_mode) + self.history_is_visible(self.gui.receive_mode) + self.server_working_on_start_button_pressed(self.gui.receive_mode) + self.server_status_indicator_says_starting(self.gui.receive_mode) + self.settings_button_is_hidden() + self.server_is_started(self.gui.receive_mode, startup_time=45000) + self.web_server_is_running() + self.have_an_onion_service() + self.have_a_slug(self.gui.receive_mode, public_mode) + self.url_description_shown(self.gui.receive_mode) + self.have_copy_url_button(self.gui.receive_mode, public_mode) + self.server_status_indicator_says_started(self.gui.receive_mode) + self.web_page(self.gui.receive_mode, 'Select the files you want to send, then click', public_mode) + self.upload_file(public_mode, '/tmp/test.txt', '/tmp/OnionShare/test.txt') + self.history_widgets_present(self.gui.receive_mode) + self.counter_incremented(self.gui.receive_mode, 1) + self.upload_file(public_mode, '/tmp/test.txt', '/tmp/OnionShare/test-2.txt') + self.counter_incremented(self.gui.receive_mode, 2) + self.upload_file(public_mode, '/tmp/testdir/test', '/tmp/OnionShare/test') + self.counter_incremented(self.gui.receive_mode, 3) + self.upload_file(public_mode, '/tmp/testdir/test', '/tmp/OnionShare/test-2') + self.counter_incremented(self.gui.receive_mode, 4) + self.history_indicator(self.gui.receive_mode, public_mode) + self.server_is_stopped(self.gui.receive_mode, False) + self.web_server_is_stopped() + self.server_status_indicator_says_closed(self.gui.receive_mode, False) + self.server_working_on_start_button_pressed(self.gui.receive_mode) + self.server_is_started(self.gui.receive_mode, startup_time=45000) + self.history_indicator(self.gui.receive_mode, public_mode) + diff --git a/tests/TorGuiShareTest.py b/tests/TorGuiShareTest.py new file mode 100644 index 00000000..53641dce --- /dev/null +++ b/tests/TorGuiShareTest.py @@ -0,0 +1,95 @@ +import requests +import zipfile +from PyQt5 import QtTest +from .TorGuiBaseTest import TorGuiBaseTest +from .GuiShareTest import GuiShareTest + +class TorGuiShareTest(TorGuiBaseTest, GuiShareTest): + def download_share(self, public_mode): + '''Test downloading a share''' + # Set up connecting to the onion + (socks_address, socks_port) = self.gui.app.onion.get_tor_socks_port() + session = requests.session() + session.proxies = {} + session.proxies['http'] = 'socks5h://{}:{}'.format(socks_address, socks_port) + + # Download files + if public_mode: + path = "http://{}/download".format(self.gui.app.onion_host) + else: + path = "http://{}/{}/download".format(self.gui.app.onion_host, self.gui.share_mode.web.slug) + response = session.get(path, stream=True) + QtTest.QTest.qWait(4000) + + if response.status_code == 200: + with open('/tmp/download.zip', 'wb') as file_to_write: + for chunk in response.iter_content(chunk_size=128): + file_to_write.write(chunk) + file_to_write.close() + zip = zipfile.ZipFile('/tmp/download.zip') + QtTest.QTest.qWait(4000) + self.assertEqual('onionshare', zip.read('test.txt').decode('utf-8')) + + + # Persistence tests + def have_same_onion(self, onion): + '''Test that we have the same onion''' + self.assertEqual(self.gui.app.onion_host, onion) + + # legacy v2 onion test + def have_v2_onion(self): + '''Test that the onion is a v2 style onion''' + self.assertRegex(self.gui.app.onion_host, r'[a-z2-7].onion') + self.assertEqual(len(self.gui.app.onion_host), 22) + + # 'Grouped' tests follow from here + + def run_all_share_mode_started_tests(self, public_mode): + '''Tests in share mode after starting a share''' + self.server_working_on_start_button_pressed(self.gui.share_mode) + self.server_status_indicator_says_starting(self.gui.share_mode) + self.add_delete_buttons_hidden() + self.settings_button_is_hidden() + self.server_is_started(self.gui.share_mode, startup_time=45000) + self.web_server_is_running() + self.have_an_onion_service() + self.have_a_slug(self.gui.share_mode, public_mode) + self.url_description_shown(self.gui.share_mode) + self.have_copy_url_button(self.gui.share_mode, public_mode) + self.server_status_indicator_says_started(self.gui.share_mode) + + + def run_all_share_mode_download_tests(self, public_mode, stay_open): + """Tests in share mode after downloading a share""" + self.web_page(self.gui.share_mode, 'Total size', public_mode) + self.download_share(public_mode) + self.history_widgets_present(self.gui.share_mode) + self.server_is_stopped(self.gui.share_mode, stay_open) + self.web_server_is_stopped() + self.server_status_indicator_says_closed(self.gui.share_mode, stay_open) + self.add_button_visible() + self.server_working_on_start_button_pressed(self.gui.share_mode) + self.server_is_started(self.gui.share_mode, startup_time=45000) + self.history_indicator(self.gui.share_mode, public_mode) + + + def run_all_share_mode_persistent_tests(self, public_mode, stay_open): + """Same as end-to-end share tests but also test the slug is the same on multiple shared""" + self.run_all_share_mode_setup_tests() + self.run_all_share_mode_started_tests(public_mode) + slug = self.gui.share_mode.server_status.web.slug + onion = self.gui.app.onion_host + self.run_all_share_mode_download_tests(public_mode, stay_open) + self.have_same_onion(onion) + self.have_same_slug(slug) + + + def run_all_share_mode_timer_tests(self, public_mode): + """Auto-stop timer tests in share mode""" + self.run_all_share_mode_setup_tests() + self.set_timeout(self.gui.share_mode, 120) + self.run_all_share_mode_started_tests(public_mode) + self.timeout_widget_hidden(self.gui.share_mode) + self.server_timed_out(self.gui.share_mode, 125000) + self.web_server_is_stopped() + diff --git a/tests/conftest.py b/tests/conftest.py index 8ac7efb8..688b22d8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,7 +8,23 @@ import tempfile import pytest -from onionshare import common, web, settings +from onionshare import common, web, settings, strings + +def pytest_addoption(parser): + parser.addoption( + "--runtor", action="store_true", default=False, help="run tor tests" + ) + + +def pytest_collection_modifyitems(config, items): + if config.getoption("--runtor"): + # --runtor given in cli: do not skip tor tests + return + skip_tor = pytest.mark.skip(reason="need --runtor option to run") + for item in items: + if "tor" in item.keywords: + item.add_marker(skip_tor) + @pytest.fixture def temp_dir_1024(): @@ -157,4 +173,5 @@ def common_obj(): def settings_obj(sys_onionshare_dev_mode, platform_linux): _common = common.Common() _common.version = 'DUMMY_VERSION_1.2.3' + strings.load_strings(_common) return settings.Settings(_common) diff --git a/tests/local_onionshare_404_public_mode_skips_ratelimit_test.py b/tests/local_onionshare_404_public_mode_skips_ratelimit_test.py new file mode 100644 index 00000000..11feb6f0 --- /dev/null +++ b/tests/local_onionshare_404_public_mode_skips_ratelimit_test.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +import unittest + +from .GuiShareTest import GuiShareTest + +class Local404PublicModeRateLimitTest(unittest.TestCase, GuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + "close_after_first_download": False, + "public_mode": True + } + cls.gui = GuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + GuiShareTest.tear_down() + + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_tests(True, True) + self.hit_404(True) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/local_onionshare_404_triggers_ratelimit_test.py b/tests/local_onionshare_404_triggers_ratelimit_test.py new file mode 100644 index 00000000..ad49c3f8 --- /dev/null +++ b/tests/local_onionshare_404_triggers_ratelimit_test.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +import unittest + +from .GuiShareTest import GuiShareTest + +class Local404RateLimitTest(unittest.TestCase, GuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + "close_after_first_download": False + } + cls.gui = GuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + GuiShareTest.tear_down() + + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_tests(False, True) + self.hit_404(False) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/local_onionshare_quitting_during_share_prompts_warning_test.py b/tests/local_onionshare_quitting_during_share_prompts_warning_test.py new file mode 100644 index 00000000..d2fe4986 --- /dev/null +++ b/tests/local_onionshare_quitting_during_share_prompts_warning_test.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +import unittest +from PyQt5 import QtCore, QtTest + +from .GuiShareTest import GuiShareTest + +class LocalQuittingDuringSharePromptsWarningTest(unittest.TestCase, GuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + "close_after_first_download": False + } + cls.gui = GuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + GuiShareTest.tear_down() + + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_tests(False, True) + # Prepare our auto-accept of prompt + QtCore.QTimer.singleShot(5000, self.accept_dialog) + # Try to close the app + self.gui.close() + # Server should still be running (we've been prompted first) + self.server_is_started(self.gui.share_mode, 0) + self.web_server_is_running() + +if __name__ == "__main__": + unittest.main() diff --git a/tests/local_onionshare_receive_mode_sender_closed_test.py b/tests/local_onionshare_receive_mode_sender_closed_test.py new file mode 100644 index 00000000..e177d2ef --- /dev/null +++ b/tests/local_onionshare_receive_mode_sender_closed_test.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +import unittest + +from .GuiReceiveTest import GuiReceiveTest + +class LocalReceiveModeSenderClosedTest(unittest.TestCase, GuiReceiveTest): + @classmethod + def setUpClass(cls): + test_settings = { + "receive_allow_receiver_shutdown": True + } + cls.gui = GuiReceiveTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + GuiReceiveTest.tear_down() + + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_receive_mode_tests(False, True) + self.run_receive_mode_sender_closed_tests(False) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/local_onionshare_receive_mode_timer_test.py b/tests/local_onionshare_receive_mode_timer_test.py new file mode 100644 index 00000000..88002f94 --- /dev/null +++ b/tests/local_onionshare_receive_mode_timer_test.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +import unittest + +from .GuiReceiveTest import GuiReceiveTest + +class LocalReceiveModeTimerTest(unittest.TestCase, GuiReceiveTest): + @classmethod + def setUpClass(cls): + test_settings = { + "public_mode": False, + "shutdown_timeout": True, + } + cls.gui = GuiReceiveTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + GuiReceiveTest.tear_down() + + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_receive_mode_timer_tests(False) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/local_onionshare_receive_mode_upload_non_writable_dir_test.py b/tests/local_onionshare_receive_mode_upload_non_writable_dir_test.py new file mode 100644 index 00000000..7d7b2780 --- /dev/null +++ b/tests/local_onionshare_receive_mode_upload_non_writable_dir_test.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +import unittest + +from .GuiReceiveTest import GuiReceiveTest + +class LocalReceiveModeUnwritableTest(unittest.TestCase, GuiReceiveTest): + @classmethod + def setUpClass(cls): + test_settings = { + "receive_allow_receiver_shutdown": True + } + cls.gui = GuiReceiveTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + GuiReceiveTest.tear_down() + + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_receive_mode_unwritable_dir_tests(False, True) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/local_onionshare_receive_mode_upload_public_mode_non_writable_dir_test.py b/tests/local_onionshare_receive_mode_upload_public_mode_non_writable_dir_test.py new file mode 100644 index 00000000..cdc4e62a --- /dev/null +++ b/tests/local_onionshare_receive_mode_upload_public_mode_non_writable_dir_test.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +import unittest + +from .GuiReceiveTest import GuiReceiveTest + +class LocalReceivePublicModeUnwritableTest(unittest.TestCase, GuiReceiveTest): + @classmethod + def setUpClass(cls): + test_settings = { + "public_mode": True, + "receive_allow_receiver_shutdown": True + } + cls.gui = GuiReceiveTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + GuiReceiveTest.tear_down() + + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_receive_mode_unwritable_dir_tests(True, True) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/local_onionshare_receive_mode_upload_public_mode_test.py b/tests/local_onionshare_receive_mode_upload_public_mode_test.py new file mode 100644 index 00000000..bedb7ae2 --- /dev/null +++ b/tests/local_onionshare_receive_mode_upload_public_mode_test.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +import unittest + +from .GuiReceiveTest import GuiReceiveTest + +class LocalReceiveModePublicModeTest(unittest.TestCase, GuiReceiveTest): + @classmethod + def setUpClass(cls): + test_settings = { + "public_mode": True, + "receive_allow_receiver_shutdown": True + } + cls.gui = GuiReceiveTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + GuiReceiveTest.tear_down() + + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_receive_mode_tests(True, True) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/local_onionshare_receive_mode_upload_test.py b/tests/local_onionshare_receive_mode_upload_test.py new file mode 100644 index 00000000..82baf3fd --- /dev/null +++ b/tests/local_onionshare_receive_mode_upload_test.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +import unittest + +from .GuiReceiveTest import GuiReceiveTest + +class LocalReceiveModeTest(unittest.TestCase, GuiReceiveTest): + @classmethod + def setUpClass(cls): + test_settings = { + "receive_allow_receiver_shutdown": True + } + cls.gui = GuiReceiveTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + GuiReceiveTest.tear_down() + + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_receive_mode_tests(False, True) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/local_onionshare_settings_dialog_test.py b/tests/local_onionshare_settings_dialog_test.py new file mode 100644 index 00000000..6d8923b6 --- /dev/null +++ b/tests/local_onionshare_settings_dialog_test.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python3 +import json +import unittest +from PyQt5 import QtCore, QtTest + +from onionshare import strings +from .SettingsGuiBaseTest import SettingsGuiBaseTest + +class SettingsGuiTest(unittest.TestCase, SettingsGuiBaseTest): + @classmethod + def setUpClass(cls): + test_settings = { + "no_bridges": False, + "tor_bridges_use_custom_bridges": "Bridge 1.2.3.4:56 EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\nBridge 5.6.7.8:910 EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\nBridge 11.12.13.14:1516 EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n", + } + cls.gui = SettingsGuiBaseTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + SettingsGuiBaseTest.tear_down() + + def test_gui(self): + self.gui.show() + # Window is shown + self.assertTrue(self.gui.isVisible()) + self.assertEqual(self.gui.windowTitle(), strings._('gui_settings_window_title')) + # Check for updates button is hidden + self.assertFalse(self.gui.check_for_updates_button.isVisible()) + + # public mode is off + self.assertFalse(self.gui.public_mode_checkbox.isChecked()) + # enable public mode + QtTest.QTest.mouseClick(self.gui.public_mode_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.public_mode_checkbox.height()/2)) + self.assertTrue(self.gui.public_mode_checkbox.isChecked()) + + # shutdown timer is off + self.assertFalse(self.gui.shutdown_timeout_checkbox.isChecked()) + # enable shutdown timer + QtTest.QTest.mouseClick(self.gui.shutdown_timeout_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.shutdown_timeout_checkbox.height()/2)) + self.assertTrue(self.gui.shutdown_timeout_checkbox.isChecked()) + + # legacy mode checkbox and related widgets + # legacy mode is off + self.assertFalse(self.gui.use_legacy_v2_onions_checkbox.isChecked()) + # persistence, stealth is hidden and disabled + self.assertFalse(self.gui.save_private_key_widget.isVisible()) + self.assertFalse(self.gui.save_private_key_checkbox.isChecked()) + self.assertFalse(self.gui.use_stealth_widget.isVisible()) + self.assertFalse(self.gui.stealth_checkbox.isChecked()) + self.assertFalse(self.gui.hidservauth_copy_button.isVisible()) + + # enable legacy mode + QtTest.QTest.mouseClick(self.gui.use_legacy_v2_onions_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.use_legacy_v2_onions_checkbox.height()/2)) + self.assertTrue(self.gui.use_legacy_v2_onions_checkbox.isChecked()) + self.assertTrue(self.gui.save_private_key_checkbox.isVisible()) + self.assertTrue(self.gui.use_stealth_widget.isVisible()) + # enable persistent mode + QtTest.QTest.mouseClick(self.gui.save_private_key_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.save_private_key_checkbox.height()/2)) + self.assertTrue(self.gui.save_private_key_checkbox.isChecked()) + # enable stealth mode + QtTest.QTest.mouseClick(self.gui.stealth_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.stealth_checkbox.height()/2)) + self.assertTrue(self.gui.stealth_checkbox.isChecked()) + # now that stealth, persistence are enabled, we can't turn off legacy mode + self.assertFalse(self.gui.use_legacy_v2_onions_checkbox.isEnabled()) + # disable stealth, persistence + QtTest.QTest.mouseClick(self.gui.save_private_key_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.save_private_key_checkbox.height()/2)) + QtTest.QTest.mouseClick(self.gui.stealth_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.stealth_checkbox.height()/2)) + # legacy mode checkbox is enabled again + self.assertTrue(self.gui.use_legacy_v2_onions_checkbox.isEnabled()) + # uncheck legacy mode + QtTest.QTest.mouseClick(self.gui.use_legacy_v2_onions_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.use_legacy_v2_onions_checkbox.height()/2)) + # legacy options hidden again + self.assertFalse(self.gui.save_private_key_widget.isVisible()) + self.assertFalse(self.gui.use_stealth_widget.isVisible()) + # enable them all again so that we can see the setting stick in settings.json + QtTest.QTest.mouseClick(self.gui.use_legacy_v2_onions_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.use_legacy_v2_onions_checkbox.height()/2)) + QtTest.QTest.mouseClick(self.gui.save_private_key_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.save_private_key_checkbox.height()/2)) + QtTest.QTest.mouseClick(self.gui.stealth_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.stealth_checkbox.height()/2)) + + + # stay open toggled off, on + self.assertTrue(self.gui.close_after_first_download_checkbox.isChecked()) + QtTest.QTest.mouseClick(self.gui.close_after_first_download_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.close_after_first_download_checkbox.height()/2)) + self.assertFalse(self.gui.close_after_first_download_checkbox.isChecked()) + + # receive mode + self.gui.downloads_dir_lineedit.setText('/tmp/OnionShareSettingsTest') + # allow receiver shutdown is on + self.assertTrue(self.gui.receive_allow_receiver_shutdown_checkbox.isChecked()) + # disable receiver shutdown + QtTest.QTest.mouseClick(self.gui.receive_allow_receiver_shutdown_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.receive_allow_receiver_shutdown_checkbox.height()/2)) + self.assertFalse(self.gui.receive_allow_receiver_shutdown_checkbox.isChecked()) + + + # bundled mode is enabled + self.assertTrue(self.gui.connection_type_bundled_radio.isEnabled()) + self.assertTrue(self.gui.connection_type_bundled_radio.isChecked()) + # bridge options are shown + self.assertTrue(self.gui.connection_type_bridges_radio_group.isVisible()) + # bridges are set to custom + self.assertFalse(self.gui.tor_bridges_no_bridges_radio.isChecked()) + self.assertTrue(self.gui.tor_bridges_use_custom_radio.isChecked()) + + # switch to obfs4 + QtTest.QTest.mouseClick(self.gui.tor_bridges_use_obfs4_radio, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.tor_bridges_use_obfs4_radio.height()/2)) + self.assertTrue(self.gui.tor_bridges_use_obfs4_radio.isChecked()) + + # custom bridges are hidden + self.assertFalse(self.gui.tor_bridges_use_custom_textbox_options.isVisible()) + # other modes are unchecked but enabled + self.assertTrue(self.gui.connection_type_automatic_radio.isEnabled()) + self.assertTrue(self.gui.connection_type_control_port_radio.isEnabled()) + self.assertTrue(self.gui.connection_type_socket_file_radio.isEnabled()) + self.assertFalse(self.gui.connection_type_automatic_radio.isChecked()) + self.assertFalse(self.gui.connection_type_control_port_radio.isChecked()) + self.assertFalse(self.gui.connection_type_socket_file_radio.isChecked()) + + # enable automatic mode + QtTest.QTest.mouseClick(self.gui.connection_type_automatic_radio, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.connection_type_automatic_radio.height()/2)) + self.assertTrue(self.gui.connection_type_automatic_radio.isChecked()) + # bundled is off + self.assertFalse(self.gui.connection_type_bundled_radio.isChecked()) + # bridges are hidden + self.assertFalse(self.gui.connection_type_bridges_radio_group.isVisible()) + + # auth type is hidden in bundled or automatic mode + self.assertFalse(self.gui.authenticate_no_auth_radio.isVisible()) + self.assertFalse(self.gui.authenticate_password_radio.isVisible()) + + # enable control port mode + QtTest.QTest.mouseClick(self.gui.connection_type_control_port_radio, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.connection_type_control_port_radio.height()/2)) + self.assertTrue(self.gui.connection_type_control_port_radio.isChecked()) + # automatic is off + self.assertFalse(self.gui.connection_type_automatic_radio.isChecked()) + # auth options appear + self.assertTrue(self.gui.authenticate_no_auth_radio.isVisible()) + self.assertTrue(self.gui.authenticate_password_radio.isVisible()) + + # enable socket mode + QtTest.QTest.mouseClick(self.gui.connection_type_socket_file_radio, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.connection_type_socket_file_radio.height()/2)) + self.assertTrue(self.gui.connection_type_socket_file_radio.isChecked()) + # control port is off + self.assertFalse(self.gui.connection_type_control_port_radio.isChecked()) + # auth options are still present + self.assertTrue(self.gui.authenticate_no_auth_radio.isVisible()) + self.assertTrue(self.gui.authenticate_password_radio.isVisible()) + + # re-enable bundled mode + QtTest.QTest.mouseClick(self.gui.connection_type_bundled_radio, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.connection_type_bundled_radio.height()/2)) + # go back to custom bridges + QtTest.QTest.mouseClick(self.gui.tor_bridges_use_custom_radio, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.tor_bridges_use_custom_radio.height()/2)) + self.assertTrue(self.gui.tor_bridges_use_custom_radio.isChecked()) + self.assertTrue(self.gui.tor_bridges_use_custom_textbox.isVisible()) + self.assertFalse(self.gui.tor_bridges_use_obfs4_radio.isChecked()) + self.gui.tor_bridges_use_custom_textbox.setPlainText('94.242.249.2:83 E25A95F1DADB739F0A83EB0223A37C02FD519306\n148.251.90.59:7510 019F727CA6DCA6CA5C90B55E477B7D87981E75BC\n93.80.47.217:41727 A6A0D497D98097FCFE91D639548EE9E34C15CDD3') + + # Test that the Settings Dialog can save the settings and close itself + QtTest.QTest.mouseClick(self.gui.save_button, QtCore.Qt.LeftButton) + self.assertFalse(self.gui.isVisible()) + + # Test our settings are reflected in the settings json + with open('/tmp/settings.json') as f: + data = json.load(f) + + self.assertTrue(data["public_mode"]) + self.assertTrue(data["shutdown_timeout"]) + self.assertTrue(data["use_legacy_v2_onions"]) + self.assertTrue(data["save_private_key"]) + self.assertTrue(data["use_stealth"]) + self.assertEqual(data["downloads_dir"], "/tmp/OnionShareSettingsTest") + self.assertFalse(data["receive_allow_receiver_shutdown"]) + self.assertFalse(data["close_after_first_download"]) + self.assertEqual(data["connection_type"], "bundled") + self.assertFalse(data["tor_bridges_use_obfs4"]) + self.assertEqual(data["tor_bridges_use_custom_bridges"], "Bridge 94.242.249.2:83 E25A95F1DADB739F0A83EB0223A37C02FD519306\nBridge 148.251.90.59:7510 019F727CA6DCA6CA5C90B55E477B7D87981E75BC\nBridge 93.80.47.217:41727 A6A0D497D98097FCFE91D639548EE9E34C15CDD3\n") + +if __name__ == "__main__": + unittest.main() diff --git a/tests/local_onionshare_share_mode_download_public_mode_test.py b/tests/local_onionshare_share_mode_download_public_mode_test.py new file mode 100644 index 00000000..d6dff13a --- /dev/null +++ b/tests/local_onionshare_share_mode_download_public_mode_test.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +import unittest + +from .GuiShareTest import GuiShareTest + +class LocalShareModePublicModeTest(unittest.TestCase, GuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + "public_mode": True, + } + cls.gui = GuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + GuiShareTest.tear_down() + + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_tests(True, False) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/local_onionshare_share_mode_download_stay_open_test.py b/tests/local_onionshare_share_mode_download_stay_open_test.py new file mode 100644 index 00000000..54d6de51 --- /dev/null +++ b/tests/local_onionshare_share_mode_download_stay_open_test.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +import unittest + +from .GuiShareTest import GuiShareTest + +class LocalShareModeStayOpenTest(unittest.TestCase, GuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + "close_after_first_download": False, + } + cls.gui = GuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + GuiShareTest.tear_down() + + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_tests(False, True) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/local_onionshare_share_mode_download_test.py b/tests/local_onionshare_share_mode_download_test.py new file mode 100644 index 00000000..ff182740 --- /dev/null +++ b/tests/local_onionshare_share_mode_download_test.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +import unittest + +from .GuiShareTest import GuiShareTest + +class LocalShareModeTest(unittest.TestCase, GuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + } + cls.gui = GuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + GuiShareTest.tear_down() + + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_tests(False, False) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/local_onionshare_share_mode_large_download_test.py b/tests/local_onionshare_share_mode_large_download_test.py new file mode 100644 index 00000000..46e6df28 --- /dev/null +++ b/tests/local_onionshare_share_mode_large_download_test.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +import unittest + +from .GuiShareTest import GuiShareTest + +class LocalShareModeLargeDownloadTest(unittest.TestCase, GuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + } + cls.gui = GuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + GuiShareTest.tear_down() + + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_large_file_tests(False, True) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/local_onionshare_share_mode_slug_persistent_test.py b/tests/local_onionshare_share_mode_slug_persistent_test.py new file mode 100644 index 00000000..a1cc6972 --- /dev/null +++ b/tests/local_onionshare_share_mode_slug_persistent_test.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +import unittest + +from .GuiShareTest import GuiShareTest + +class LocalShareModePersistentSlugTest(unittest.TestCase, GuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + "public_mode": False, + "slug": "", + "save_private_key": True, + "close_after_first_download": False, + } + cls.gui = GuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + GuiShareTest.tear_down() + + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_persistent_tests(False, True) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/local_onionshare_share_mode_timer_test.py b/tests/local_onionshare_share_mode_timer_test.py new file mode 100644 index 00000000..41a6268d --- /dev/null +++ b/tests/local_onionshare_share_mode_timer_test.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +import unittest + +from .GuiShareTest import GuiShareTest + +class LocalShareModeTimerTest(unittest.TestCase, GuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + "public_mode": False, + "shutdown_timeout": True, + } + cls.gui = GuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + GuiShareTest.tear_down() + + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_timer_tests(False) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/local_onionshare_share_mode_timer_too_short_test.py b/tests/local_onionshare_share_mode_timer_too_short_test.py new file mode 100644 index 00000000..41c30883 --- /dev/null +++ b/tests/local_onionshare_share_mode_timer_too_short_test.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +import unittest +from PyQt5 import QtCore, QtTest + +from .GuiShareTest import GuiShareTest + +class LocalShareModeTimerTooShortTest(unittest.TestCase, GuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + "public_mode": False, + "shutdown_timeout": True, + } + cls.gui = GuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + GuiShareTest.tear_down() + + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_setup_tests() + # Set a low timeout + self.set_timeout(self.gui.share_mode, 2) + QtTest.QTest.qWait(3000) + QtCore.QTimer.singleShot(4000, self.accept_dialog) + QtTest.QTest.mouseClick(self.gui.share_mode.server_status.server_button, QtCore.Qt.LeftButton) + self.assertEqual(self.gui.share_mode.server_status.status, 0) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/local_onionshare_share_mode_unreadable_file_test.py b/tests/local_onionshare_share_mode_unreadable_file_test.py new file mode 100644 index 00000000..38a0e847 --- /dev/null +++ b/tests/local_onionshare_share_mode_unreadable_file_test.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +import unittest + +from .GuiShareTest import GuiShareTest + +class LocalShareModeUnReadableFileTest(unittest.TestCase, GuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + } + cls.gui = GuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + GuiShareTest.tear_down() + + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_unreadable_file_tests() + +if __name__ == "__main__": + unittest.main() diff --git a/tests/onionshare_790_cancel_on_second_share_test.py b/tests/onionshare_790_cancel_on_second_share_test.py new file mode 100644 index 00000000..b144edf3 --- /dev/null +++ b/tests/onionshare_790_cancel_on_second_share_test.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +import pytest +import unittest + +from .TorGuiShareTest import TorGuiShareTest + +# Tests #790 regression +class ShareModeCancelSecondShareTest(unittest.TestCase, TorGuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + "close_after_first_download": True + } + cls.gui = TorGuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + TorGuiShareTest.tear_down() + + @pytest.mark.tor + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_tests(False, False) + self.cancel_the_share(self.gui.share_mode) + self.server_is_stopped(self.gui.share_mode, False) + self.web_server_is_stopped() + +if __name__ == "__main__": + unittest.main() diff --git a/tests/onionshare_receive_mode_upload_public_mode_test.py b/tests/onionshare_receive_mode_upload_public_mode_test.py new file mode 100644 index 00000000..275e5953 --- /dev/null +++ b/tests/onionshare_receive_mode_upload_public_mode_test.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +import pytest +import unittest + +from .TorGuiReceiveTest import TorGuiReceiveTest + +class ReceiveModeTest(unittest.TestCase, TorGuiReceiveTest): + @classmethod + def setUpClass(cls): + test_settings = { + "public_mode": True, + "receive_allow_receiver_shutdown": True + } + cls.gui = TorGuiReceiveTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + TorGuiReceiveTest.tear_down() + + @pytest.mark.tor + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_receive_mode_tests(True, True) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/onionshare_receive_mode_upload_test.py b/tests/onionshare_receive_mode_upload_test.py new file mode 100644 index 00000000..f9914659 --- /dev/null +++ b/tests/onionshare_receive_mode_upload_test.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +import pytest +import unittest + +from .TorGuiReceiveTest import TorGuiReceiveTest + +class ReceiveModeTest(unittest.TestCase, TorGuiReceiveTest): + @classmethod + def setUpClass(cls): + test_settings = { + "receive_allow_receiver_shutdown": True + } + cls.gui = TorGuiReceiveTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + TorGuiReceiveTest.tear_down() + + @pytest.mark.tor + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_receive_mode_tests(False, True) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/onionshare_share_mode_cancel_share_test.py b/tests/onionshare_share_mode_cancel_share_test.py new file mode 100644 index 00000000..5f4d6fb3 --- /dev/null +++ b/tests/onionshare_share_mode_cancel_share_test.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +import pytest +import unittest + +from .TorGuiShareTest import TorGuiShareTest + +class ShareModeCancelTest(unittest.TestCase, TorGuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + } + cls.gui = TorGuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + TorGuiShareTest.tear_down() + + @pytest.mark.tor + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_setup_tests() + self.cancel_the_share(self.gui.share_mode) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/onionshare_share_mode_download_public_mode_test.py b/tests/onionshare_share_mode_download_public_mode_test.py new file mode 100644 index 00000000..672603ce --- /dev/null +++ b/tests/onionshare_share_mode_download_public_mode_test.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +import pytest +import unittest + +from .TorGuiShareTest import TorGuiShareTest + +class ShareModePublicModeTest(unittest.TestCase, TorGuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + "public_mode": True, + } + cls.gui = TorGuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + TorGuiShareTest.tear_down() + + @pytest.mark.tor + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_tests(True, False) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/onionshare_share_mode_download_stay_open_test.py b/tests/onionshare_share_mode_download_stay_open_test.py new file mode 100644 index 00000000..e7e64083 --- /dev/null +++ b/tests/onionshare_share_mode_download_stay_open_test.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +import pytest +import unittest + +from .TorGuiShareTest import TorGuiShareTest + +class ShareModeStayOpenTest(unittest.TestCase, TorGuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + "close_after_first_download": False, + } + cls.gui = TorGuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + TorGuiShareTest.tear_down() + + @pytest.mark.tor + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_tests(False, True) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/onionshare_share_mode_download_test.py b/tests/onionshare_share_mode_download_test.py new file mode 100644 index 00000000..7d414e5d --- /dev/null +++ b/tests/onionshare_share_mode_download_test.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +import pytest +import unittest + +from .TorGuiShareTest import TorGuiShareTest + +class ShareModeTest(unittest.TestCase, TorGuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + } + cls.gui = TorGuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + TorGuiShareTest.tear_down() + + @pytest.mark.tor + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_tests(False, False) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/onionshare_share_mode_persistent_test.py b/tests/onionshare_share_mode_persistent_test.py new file mode 100644 index 00000000..86b61a81 --- /dev/null +++ b/tests/onionshare_share_mode_persistent_test.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +import pytest +import unittest + +from .TorGuiShareTest import TorGuiShareTest + +class ShareModePersistentSlugTest(unittest.TestCase, TorGuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + "use_legacy_v2_onions": True, + "public_mode": False, + "slug": "", + "save_private_key": True, + "close_after_first_download": False, + } + cls.gui = TorGuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + TorGuiShareTest.tear_down() + + @pytest.mark.tor + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_persistent_tests(False, True) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/onionshare_share_mode_stealth_test.py b/tests/onionshare_share_mode_stealth_test.py new file mode 100644 index 00000000..b16669e6 --- /dev/null +++ b/tests/onionshare_share_mode_stealth_test.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +import pytest +import unittest + +from .TorGuiShareTest import TorGuiShareTest + +class ShareModeStealthTest(unittest.TestCase, TorGuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + "use_legacy_v2_onions": True, + "use_stealth": True, + } + cls.gui = TorGuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + TorGuiShareTest.tear_down() + + @pytest.mark.tor + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_setup_tests() + self.run_all_share_mode_started_tests(False) + self.hidserv_auth_string() + self.copy_have_hidserv_auth_button(self.gui.share_mode) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/onionshare_share_mode_timer_test.py b/tests/onionshare_share_mode_timer_test.py new file mode 100644 index 00000000..a13d2d80 --- /dev/null +++ b/tests/onionshare_share_mode_timer_test.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +import pytest +import unittest + +from .TorGuiShareTest import TorGuiShareTest + +class ShareModeTimerTest(unittest.TestCase, TorGuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + "public_mode": False, + "shutdown_timeout": True, + } + cls.gui = TorGuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + TorGuiShareTest.tear_down() + + @pytest.mark.tor + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_timer_tests(False) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/onionshare_share_mode_tor_connection_killed_test.py b/tests/onionshare_share_mode_tor_connection_killed_test.py new file mode 100644 index 00000000..62513a12 --- /dev/null +++ b/tests/onionshare_share_mode_tor_connection_killed_test.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +import pytest +import unittest + +from .TorGuiShareTest import TorGuiShareTest + +class ShareModeTorConnectionKilledTest(unittest.TestCase, TorGuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + } + cls.gui = TorGuiShareTest.set_up(test_settings) + + @pytest.mark.tor + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_setup_tests() + self.run_all_share_mode_started_tests(False) + self.tor_killed_statusbar_message_shown(self.gui.share_mode) + self.server_is_stopped(self.gui.share_mode, False) + self.web_server_is_stopped() + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/onionshare_share_mode_v2_onion_test.py b/tests/onionshare_share_mode_v2_onion_test.py new file mode 100644 index 00000000..c932abf9 --- /dev/null +++ b/tests/onionshare_share_mode_v2_onion_test.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +import pytest +import unittest + +from .TorGuiShareTest import TorGuiShareTest + +class ShareModeV2OnionTest(unittest.TestCase, TorGuiShareTest): + @classmethod + def setUpClass(cls): + test_settings = { + "use_legacy_v2_onions": True, + } + cls.gui = TorGuiShareTest.set_up(test_settings) + + @classmethod + def tearDownClass(cls): + TorGuiShareTest.tear_down() + + @pytest.mark.tor + def test_gui(self): + self.run_all_common_setup_tests() + self.run_all_share_mode_tests(False, False) + self.have_v2_onion() + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_onionshare_settings.py b/tests/test_onionshare_settings.py index 49c709e7..bb619c4d 100644 --- a/tests/test_onionshare_settings.py +++ b/tests/test_onionshare_settings.py @@ -40,7 +40,7 @@ def settings_obj(sys_onionshare_dev_mode, platform_linux): class TestSettings: def test_init(self, settings_obj): - assert settings_obj._settings == settings_obj.default_settings == { + expected_settings = { 'version': 'DUMMY_VERSION_1.2.3', 'connection_type': 'bundled', 'control_port_address': '127.0.0.1', @@ -67,6 +67,11 @@ class TestSettings: 'downloads_dir': os.path.expanduser('~/OnionShare'), 'public_mode': False } + for key in settings_obj._settings: + # Skip locale, it will not always default to the same thing + if key != 'locale': + assert settings_obj._settings[key] == settings_obj.default_settings[key] + assert settings_obj._settings[key] == expected_settings[key] def test_fill_in_defaults(self, settings_obj): del settings_obj._settings['version'] diff --git a/tests/test_onionshare_strings.py b/tests/test_onionshare_strings.py index d3d40c8f..ea57e3a9 100644 --- a/tests/test_onionshare_strings.py +++ b/tests/test_onionshare_strings.py @@ -23,7 +23,7 @@ import types import pytest from onionshare import strings - +from onionshare.settings import Settings # # Stub get_resource_path so it finds the correct path while running tests # def get_resource_path(filename): @@ -32,12 +32,6 @@ from onionshare import strings # return path # common.get_resource_path = get_resource_path - -def test_starts_with_empty_strings(): - """ Creates an empty strings dict by default """ - assert strings.strings == {} - - def test_underscore_is_function(): assert callable(strings._) and isinstance(strings._, types.FunctionType) @@ -46,6 +40,7 @@ class TestLoadStrings: def test_load_strings_defaults_to_english( self, common_obj, locale_en, sys_onionshare_dev_mode): """ load_strings() loads English by default """ + common_obj.settings = Settings(common_obj) strings.load_strings(common_obj) assert strings._('preparing_files') == "Compressing files." @@ -53,11 +48,15 @@ class TestLoadStrings: def test_load_strings_loads_other_languages( self, common_obj, locale_fr, sys_onionshare_dev_mode): """ load_strings() loads other languages in different locales """ - strings.load_strings(common_obj, "fr") + common_obj.settings = Settings(common_obj) + common_obj.settings.set('locale', 'fr') + strings.load_strings(common_obj) assert strings._('preparing_files') == "Préparation des fichiers à partager." def test_load_invalid_locale( self, common_obj, locale_invalid, sys_onionshare_dev_mode): """ load_strings() raises a KeyError for an invalid locale """ with pytest.raises(KeyError): - strings.load_strings(common_obj, 'XX') + common_obj.settings = Settings(common_obj) + common_obj.settings.set('locale', 'XX') + strings.load_strings(common_obj) diff --git a/tests/test_onionshare_web.py b/tests/test_onionshare_web.py index 3d6f34a1..3f9540ae 100644 --- a/tests/test_onionshare_web.py +++ b/tests/test_onionshare_web.py @@ -31,6 +31,7 @@ import tempfile import pytest from onionshare.common import Common +from onionshare import strings from onionshare.web import Web from onionshare.settings import Settings @@ -41,7 +42,7 @@ RANDOM_STR_REGEX = re.compile(r'^[a-z2-7]+$') def web_obj(common_obj, mode, num_files=0): """ Creates a Web object, in either share mode or receive mode, ready for testing """ common_obj.load_settings() - + strings.load_strings(common_obj) web = Web(common_obj, False, mode) web.generate_slug() web.stay_open = True |