Fix CLI tests, and also fix bug related to autostop_sharing that the tests found

This commit is contained in:
Micah Lee 2019-11-02 17:01:47 -07:00
parent 598db21dcd
commit 87918c5d89
No known key found for this signature in database
GPG key ID: 403C2657CD994F73
8 changed files with 60 additions and 69 deletions

View file

@ -282,7 +282,7 @@ def main(cwd=None):
) )
sys.exit() sys.exit()
app.start_onion_service(False, True) app.start_onion_service(mode_settings, False, True)
url = build_url(mode_settings, app, web) url = build_url(mode_settings, app, web)
schedule = datetime.now() + timedelta(seconds=autostart_timer) schedule = datetime.now() + timedelta(seconds=autostart_timer)
if mode == "receive": if mode == "receive":
@ -318,9 +318,9 @@ def main(cwd=None):
print("Waiting for the scheduled time before starting...") print("Waiting for the scheduled time before starting...")
app.onion.cleanup(False) app.onion.cleanup(False)
time.sleep(autostart_timer) time.sleep(autostart_timer)
app.start_onion_service() app.start_onion_service(mode_settings)
else: else:
app.start_onion_service() app.start_onion_service(mode_settings)
except KeyboardInterrupt: except KeyboardInterrupt:
print("") print("")
sys.exit() sys.exit()

View file

@ -17,6 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import os
import pwd
class ModeSettings: class ModeSettings:
@ -43,7 +45,7 @@ class ModeSettings:
"client_auth": False, "client_auth": False,
}, },
"share": {"autostop_sharing": True}, "share": {"autostop_sharing": True},
"receive": {"data_dir": self.common.settings.build_default_data_dir()}, "receive": {"data_dir": self.build_default_data_dir()},
"website": {"disable_csp": False}, "website": {"disable_csp": False},
} }
@ -52,3 +54,21 @@ class ModeSettings:
def set(self, group, key, val): def set(self, group, key, val):
self.settings[group][key] = val self.settings[group][key] = val
def build_default_data_dir(self):
"""
Returns the path of the default Downloads directory for receive mode.
"""
if self.common.platform == "Darwin":
# We can't use os.path.expanduser() in macOS because in the sandbox it
# returns the path to the sandboxed homedir
real_homedir = pwd.getpwuid(os.getuid()).pw_dir
return os.path.join(real_homedir, "OnionShare")
elif self.common.platform == "Windows":
# On Windows, os.path.expanduser() needs to use backslash, or else it
# retains the forward slash, which breaks opening the folder in explorer.
return os.path.expanduser("~\OnionShare")
else:
# All other OSes
return os.path.expanduser("~/OnionShare")

View file

@ -63,7 +63,9 @@ class OnionShare(object):
except: except:
raise OSError(strings._("no_available_port")) raise OSError(strings._("no_available_port"))
def start_onion_service(self, await_publication=True, save_scheduled_key=False): def start_onion_service(
self, mode_settings, await_publication=True, save_scheduled_key=False
):
""" """
Start the onionshare onion service. Start the onionshare onion service.
""" """
@ -83,7 +85,7 @@ class OnionShare(object):
self.port, await_publication, save_scheduled_key self.port, await_publication, save_scheduled_key
) )
if self.stealth: if mode_settings.get("general", "client_auth"):
self.auth_string = self.onion.auth_string self.auth_string = self.onion.auth_string
def cleanup(self): def cleanup(self):

View file

@ -122,7 +122,7 @@ class Settings(object):
"public_mode": False, "public_mode": False,
"password": "", "password": "",
"hidservauth_string": "", "hidservauth_string": "",
"data_dir": self.build_default_data_dir(), "data_dir": "",
"csp_header_disabled": False, "csp_header_disabled": False,
"locale": None, # this gets defined in fill_in_defaults() "locale": None, # this gets defined in fill_in_defaults()
} }
@ -163,24 +163,6 @@ class Settings(object):
""" """
return os.path.join(self.common.build_data_dir(), "onionshare.json") return os.path.join(self.common.build_data_dir(), "onionshare.json")
def build_default_data_dir(self):
"""
Returns the path of the default Downloads directory for receive mode.
"""
if self.common.platform == "Darwin":
# We can't use os.path.expanduser() in macOS because in the sandbox it
# returns the path to the sandboxed homedir
real_homedir = pwd.getpwuid(os.getuid()).pw_dir
return os.path.join(real_homedir, "OnionShare")
elif self.common.platform == "Windows":
# On Windows, os.path.expanduser() needs to use backslash, or else it
# retains the forward slash, which breaks opening the folder in explorer.
return os.path.expanduser("~\OnionShare")
else:
# All other OSes
return os.path.expanduser("~/OnionShare")
def load(self): def load(self):
""" """
Load the settings from file. Load the settings from file.

View file

@ -38,7 +38,7 @@ class ShareModeWeb(SendBaseModeWeb):
# Deny new downloads if "Stop sharing after files have been sent" is checked and there is # Deny new downloads if "Stop sharing after files have been sent" is checked and there is
# currently a download # currently a download
deny_download = ( deny_download = (
not self.web.settings.get("share", "autostop_sharing") self.web.settings.get("share", "autostop_sharing")
and self.download_in_progress and self.download_in_progress
) )
if deny_download: if deny_download:
@ -64,7 +64,7 @@ class ShareModeWeb(SendBaseModeWeb):
# Deny new downloads if "Stop After First Download" is checked and there is # Deny new downloads if "Stop After First Download" is checked and there is
# currently a download # currently a download
deny_download = ( deny_download = (
not self.web.settings.get("share", "autostop_sharing") self.web.settings.get("share", "autostop_sharing")
and self.download_in_progress and self.download_in_progress
) )
if deny_download: if deny_download:
@ -102,7 +102,7 @@ class ShareModeWeb(SendBaseModeWeb):
def generate(): def generate():
# Starting a new download # Starting a new download
if not self.web.settings.get("share", "autostop_sharing"): if self.web.settings.get("share", "autostop_sharing"):
self.download_in_progress = True self.download_in_progress = True
chunk_size = 102400 # 100kb chunk_size = 102400 # 100kb
@ -167,14 +167,11 @@ class ShareModeWeb(SendBaseModeWeb):
sys.stdout.write("\n") sys.stdout.write("\n")
# Download is finished # Download is finished
if not self.web.settings.get("share", "autostop_sharing"): if self.web.settings.get("share", "autostop_sharing"):
self.download_in_progress = False self.download_in_progress = False
# Close the server, if necessary # Close the server, if necessary
if ( if self.web.settings.get("share", "autostop_sharing") and not canceled:
not self.web.settings.get("share", "autostop_sharing")
and not canceled
):
print("Stopped because transfer is complete") print("Stopped because transfer is complete")
self.web.running = False self.web.running = False
try: try:

View file

@ -61,7 +61,7 @@ class OnionThread(QtCore.QThread):
try: try:
if self.mode.obtain_onion_early: if self.mode.obtain_onion_early:
self.mode.app.start_onion_service( self.mode.app.start_onion_service(
await_publication=False, save_scheduled_key=True self.mode.settings, await_publication=False, save_scheduled_key=True
) )
# wait for modules in thread to load, preventing a thread-related cx_Freeze crash # wait for modules in thread to load, preventing a thread-related cx_Freeze crash
time.sleep(0.2) time.sleep(0.2)
@ -69,7 +69,9 @@ class OnionThread(QtCore.QThread):
# Unregister the onion so we can use it in the next OnionThread # Unregister the onion so we can use it in the next OnionThread
self.mode.app.onion.cleanup(False) self.mode.app.onion.cleanup(False)
else: else:
self.mode.app.start_onion_service(await_publication=True) self.mode.app.start_onion_service(
self.mode.settings, await_publication=True
)
# wait for modules in thread to load, preventing a thread-related cx_Freeze crash # wait for modules in thread to load, preventing a thread-related cx_Freeze crash
time.sleep(0.2) time.sleep(0.2)
# start onionshare http service in new thread # start onionshare http service in new thread

View file

@ -23,13 +23,13 @@ import pytest
from onionshare import OnionShare from onionshare import OnionShare
from onionshare.common import Common from onionshare.common import Common
from onionshare.mode_settings import ModeSettings
class MyOnion: class MyOnion:
def __init__(self, stealth=False): def __init__(self):
self.auth_string = "TestHidServAuth" self.auth_string = "TestHidServAuth"
self.private_key = "" self.private_key = ""
self.stealth = stealth
self.scheduled_key = None self.scheduled_key = None
@staticmethod @staticmethod
@ -43,38 +43,27 @@ def onionshare_obj():
return OnionShare(common, MyOnion()) return OnionShare(common, MyOnion())
@pytest.fixture
def mode_settings_obj():
common = Common()
return ModeSettings(common)
class TestOnionShare: class TestOnionShare:
def test_init(self, onionshare_obj): def test_init(self, onionshare_obj):
assert onionshare_obj.hidserv_dir is None assert onionshare_obj.hidserv_dir is None
assert onionshare_obj.onion_host is None assert onionshare_obj.onion_host is None
assert onionshare_obj.stealth is None
assert onionshare_obj.cleanup_filenames == [] assert onionshare_obj.cleanup_filenames == []
assert onionshare_obj.local_only is False assert onionshare_obj.local_only is False
def test_set_stealth_true(self, onionshare_obj): def test_start_onion_service(self, onionshare_obj, mode_settings_obj):
onionshare_obj.set_stealth(True) onionshare_obj.start_onion_service(mode_settings_obj)
assert onionshare_obj.stealth is True
assert onionshare_obj.onion.stealth is True
def test_set_stealth_false(self, onionshare_obj):
onionshare_obj.set_stealth(False)
assert onionshare_obj.stealth is False
assert onionshare_obj.onion.stealth is False
def test_start_onion_service(self, onionshare_obj):
onionshare_obj.set_stealth(False)
onionshare_obj.start_onion_service()
assert 17600 <= onionshare_obj.port <= 17650 assert 17600 <= onionshare_obj.port <= 17650
assert onionshare_obj.onion_host == "test_service_id.onion" assert onionshare_obj.onion_host == "test_service_id.onion"
def test_start_onion_service_stealth(self, onionshare_obj): def test_start_onion_service_local_only(self, onionshare_obj, mode_settings_obj):
onionshare_obj.set_stealth(True)
onionshare_obj.start_onion_service()
assert onionshare_obj.auth_string == "TestHidServAuth"
def test_start_onion_service_local_only(self, onionshare_obj):
onionshare_obj.local_only = True onionshare_obj.local_only = True
onionshare_obj.start_onion_service() onionshare_obj.start_onion_service(mode_settings_obj)
assert onionshare_obj.onion_host == "127.0.0.1:{}".format(onionshare_obj.port) assert onionshare_obj.onion_host == "127.0.0.1:{}".format(onionshare_obj.port)
def test_cleanup(self, onionshare_obj, temp_dir_1024, temp_file_1024): def test_cleanup(self, onionshare_obj, temp_dir_1024, temp_file_1024):

View file

@ -36,6 +36,7 @@ from onionshare.common import Common
from onionshare import strings from onionshare import strings
from onionshare.web import Web from onionshare.web import Web
from onionshare.settings import Settings from onionshare.settings import Settings
from onionshare.mode_settings import ModeSettings
DEFAULT_ZW_FILENAME_REGEX = re.compile(r"^onionshare_[a-z2-7]{6}.zip$") DEFAULT_ZW_FILENAME_REGEX = re.compile(r"^onionshare_[a-z2-7]{6}.zip$")
RANDOM_STR_REGEX = re.compile(r"^[a-z2-7]+$") RANDOM_STR_REGEX = re.compile(r"^[a-z2-7]+$")
@ -45,9 +46,9 @@ def web_obj(common_obj, mode, num_files=0):
""" Creates a Web object, in either share mode or receive mode, ready for testing """ """ Creates a Web object, in either share mode or receive mode, ready for testing """
common_obj.settings = Settings(common_obj) common_obj.settings = Settings(common_obj)
strings.load_strings(common_obj) strings.load_strings(common_obj)
web = Web(common_obj, False, mode) mode_settings = ModeSettings(common_obj)
web = Web(common_obj, False, mode_settings, mode)
web.generate_password() web.generate_password()
web.stay_open = True
web.running = True web.running = True
web.app.testing = True web.app.testing = True
@ -56,7 +57,7 @@ def web_obj(common_obj, mode, num_files=0):
if mode == "share": if mode == "share":
# Add files # Add files
files = [] files = []
for i in range(num_files): for _ in range(num_files):
with tempfile.NamedTemporaryFile(delete=False) as tmp_file: with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
tmp_file.write(b"*" * 1024) tmp_file.write(b"*" * 1024)
files.append(tmp_file.name) files.append(tmp_file.name)
@ -94,9 +95,9 @@ class TestWeb:
assert res.status_code == 200 assert res.status_code == 200
assert res.mimetype == "application/zip" assert res.mimetype == "application/zip"
def test_share_mode_close_after_first_download_on(self, common_obj, temp_file_1024): def test_share_mode_autostop_sharing_on(self, common_obj, temp_file_1024):
web = web_obj(common_obj, "share", 3) web = web_obj(common_obj, "share", 3)
web.stay_open = False web.settings.set("share", "autostop_sharing", True)
assert web.running == True assert web.running == True
@ -109,11 +110,9 @@ class TestWeb:
assert web.running == False assert web.running == False
def test_share_mode_close_after_first_download_off( def test_share_mode_autostop_sharing_off(self, common_obj, temp_file_1024):
self, common_obj, temp_file_1024
):
web = web_obj(common_obj, "share", 3) web = web_obj(common_obj, "share", 3)
web.stay_open = True web.settings.set("share", "autostop_sharing", False)
assert web.running == True assert web.running == True
@ -147,7 +146,7 @@ class TestWeb:
def test_public_mode_on(self, common_obj): def test_public_mode_on(self, common_obj):
web = web_obj(common_obj, "receive") web = web_obj(common_obj, "receive")
common_obj.settings.set("public_mode", True) web.settings.set("general", "public", True)
with web.app.test_client() as c: with web.app.test_client() as c:
# Loading / should work without auth # Loading / should work without auth
@ -157,7 +156,7 @@ class TestWeb:
def test_public_mode_off(self, common_obj): def test_public_mode_off(self, common_obj):
web = web_obj(common_obj, "receive") web = web_obj(common_obj, "receive")
common_obj.settings.set("public_mode", False) web.settings.set("general", "public", False)
with web.app.test_client() as c: with web.app.test_client() as c:
# Load / without auth # Load / without auth