Skip to content

Commit

Permalink
Merge branch 'master' into work/pause-sync-when-metered
Browse files Browse the repository at this point in the history
  • Loading branch information
TheOneRing authored Jan 5, 2024
2 parents 7e0d30a + ec3c924 commit 612e416
Show file tree
Hide file tree
Showing 45 changed files with 1,010 additions and 930 deletions.
2 changes: 1 addition & 1 deletion .drone.star
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,9 @@ def unit_test_pipeline(ctx):
}]

def gui_test_pipeline(ctx):
squish_parameters = "--reportgen html,%s --envvar QT_LOGGING_RULES=sync.httplogger=true;gui.socketapi=false --tags ~@skip --tags ~@skipOnLinux" % dir["guiTestReport"]
pipelines = []
for server, params in config["gui-tests"]["servers"].items():
squish_parameters = "--reportgen html,%s --envvar QT_LOGGING_RULES=sync.httplogger=true;gui.socketapi=false --tags ~@skip --tags ~@skipOnLinux" % dir["guiTestReport"]
if params.get("skip", False):
continue
if ctx.build.event == "pull_request" and params.get("skip_in_pr", False) and not "full-ci" in ctx.build.title.lower():
Expand Down
39 changes: 38 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Table of Contents

* [Changelog for unreleased](#changelog-for-owncloud-desktop-client-unreleased-unreleased)
* [Changelog for 5.2.1](#changelog-for-owncloud-desktop-client-521-2024-01-04)
* [Changelog for 5.2.0](#changelog-for-owncloud-desktop-client-520-2023-11-27)
* [Changelog for 5.1.2](#changelog-for-owncloud-desktop-client-512-2023-11-10)
* [Changelog for 5.1.1](#changelog-for-owncloud-desktop-client-511-2023-11-09)
Expand Down Expand Up @@ -38,7 +39,7 @@
The following sections list the changes in ownCloud Desktop Client unreleased relevant to
ownCloud admins and users.

[unreleased]: https://github.com/owncloud/client/compare/v5.2.0...master
[unreleased]: https://github.com/owncloud/client/compare/v5.2.1...master

## Summary

Expand All @@ -47,6 +48,7 @@ ownCloud admins and users.
* Change - Remove unused command line option --language: [#11245](https://github.com/owncloud/client/issues/11245)
* Change - Windows: always use fusion style: [#11275](https://github.com/owncloud/client/issues/11275)
* Change - Deprecate suffix VFS: [#11325](https://github.com/owncloud/client/issues/11325)
* Enhancement - Add support to provide a list of ports for the OAuth process: [#11276](https://github.com/owncloud/client/issues/11276)
* Enhancement - Include recent changes in scheduled syncs: [#11347](https://github.com/owncloud/client/pull/11347)

## Details
Expand Down Expand Up @@ -92,13 +94,48 @@ ownCloud admins and users.

https://github.com/owncloud/client/issues/11325

* Enhancement - Add support to provide a list of ports for the OAuth process: [#11276](https://github.com/owncloud/client/issues/11276)

We added a branding option that enables us to specify a list of ports that are
used for the local server during the OAuth process.

https://github.com/owncloud/client/issues/11276

* Enhancement - Include recent changes in scheduled syncs: [#11347](https://github.com/owncloud/client/pull/11347)

When starting a new sync we now also include the recent change events in the
discovery.

https://github.com/owncloud/client/pull/11347

# Changelog for ownCloud Desktop Client [5.2.1] (2024-01-04)

The following sections list the changes in ownCloud Desktop Client 5.2.1 relevant to
ownCloud admins and users.

[5.2.1]: https://github.com/owncloud/client/compare/v5.2.0...v5.2.1

## Summary

* Bugfix - Client stuck in reconnecting: [#11274](https://github.com/owncloud/client/issues/11274)
* Enhancement - Improved reliability for persisting settings: [#11413](https://github.com/owncloud/client/pull/11413)

## Details

* Bugfix - Client stuck in reconnecting: [#11274](https://github.com/owncloud/client/issues/11274)

We fixed a bug where the client got stuck while reconnecting to the server.

https://github.com/owncloud/client/issues/11274

* Enhancement - Improved reliability for persisting settings: [#11413](https://github.com/owncloud/client/pull/11413)

We improved the reliability of saving accounts. This might fix an issue where
sync connections were lost at random.

https://github.com/owncloud/client/issues/11411
https://github.com/owncloud/client/pull/11413

# Changelog for ownCloud Desktop Client [5.2.0] (2023-11-27)

The following sections list the changes in ownCloud Desktop Client 5.2.0 relevant to
Expand Down
2 changes: 1 addition & 1 deletion VERSION.cmake
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
set( MIRALL_VERSION_MAJOR 6 )
set( MIRALL_VERSION_MINOR 0 )
set( MIRALL_VERSION_PATCH 0 )
set( MIRALL_VERSION_YEAR 2023 )
set( MIRALL_VERSION_YEAR 2024 )
set( MIRALL_SOVERSION 0 )

if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
Expand Down
5 changes: 5 additions & 0 deletions changelog/5.2.1_2024-01-04/11274
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Bugfix: Client stuck in reconnecting

We fixed a bug where the client got stuck while reconnecting to the server.

https://github.com/owncloud/client/issues/11274
7 changes: 7 additions & 0 deletions changelog/5.2.1_2024-01-04/11413
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Enhancement: Improved reliability for persisting settings

We improved the reliability of saving accounts.
This might fix an issue where sync connections were lost at random.

https://github.com/owncloud/client/pull/11413
https://github.com/owncloud/client/issues/11411
5 changes: 5 additions & 0 deletions changelog/unreleased/11276
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Enhancement: Add support to provide a list of ports for the OAuth process

We added a branding option that enables us to specify a list of ports that are used for the local server during the OAuth process.

https://github.com/owncloud/client/issues/11276
45 changes: 20 additions & 25 deletions src/common/utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,36 +328,32 @@ void Utility::crash()

QString Utility::timeAgoInWords(const QDateTime &dt, const QDateTime &from)
{
QDateTime now = QDateTime::currentDateTimeUtc();
const QDateTime now = from.isValid() ? from : QDateTime::currentDateTimeUtc();

if (from.isValid()) {
now = from;
if (dt.daysTo(now) > 0) {
return QObject::tr("%n day(s) ago", "", dt.daysTo(now));
}

if (dt.daysTo(now) > 0) {
int dtn = dt.daysTo(now);
return QObject::tr("%n day(s) ago", "", dtn);
} else {
qint64 secs = dt.secsTo(now);
if (secs < 0) {
return QObject::tr("in the future");
}
if (floor(secs / 3600.0) > 0) {
int hours = floor(secs / 3600.0);
return (QObject::tr("%n hour(s) ago", "", hours));
const qint64 secs = dt.secsTo(now);
if (secs < 0) {
return QObject::tr("in the future");
}

if (floor(secs / 3600.0) > 0) {
const int hours = floor(secs / 3600.0);
return (QObject::tr("%n hour(s) ago", "", hours));
}

const int minutes = qRound(secs / 60.0);
if (minutes == 0) {
if (secs < 5) {
return QObject::tr("now");
} else {
int minutes = qRound(secs / 60.0);
if (minutes == 0) {
if (secs < 5) {
return QObject::tr("now");
} else {
return QObject::tr("Less than a minute ago");
}
}
return (QObject::tr("%n minute(s) ago", "", minutes));
return QObject::tr("less than a minute ago");
}
}
return QObject::tr("Some time ago");

return (QObject::tr("%n minute(s) ago", "", minutes));
}

void Utility::sortFilenames(QStringList &fileNames)
Expand Down Expand Up @@ -532,7 +528,6 @@ QString Utility::appImageLocation()
return value;
#else
Q_UNREACHABLE();
return QString();
#endif
}

Expand Down
8 changes: 4 additions & 4 deletions src/gui/fetchserversettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ void FetchServerSettingsJob::start()
job->setAuthenticationJob(isAuthJob());
job->setTimeout(timeoutC);

QObject::connect(job, &JsonApiJob::finishedSignal, this, [job, this] {
connect(job, &JsonApiJob::finishedSignal, this, [job, this] {
auto caps =
job->data().value(QStringLiteral("ocs")).toObject().value(QStringLiteral("data")).toObject().value(QStringLiteral("capabilities")).toObject();
qCInfo(lcfetchserversettings) << "Server capabilities" << caps;
Expand All @@ -59,9 +59,9 @@ void FetchServerSettingsJob::start()
_account->setCapabilities({_account->url(), caps.toVariantMap()});
if (checkServerInfo()) {
auto *userJob = new JsonApiJob(_account, QStringLiteral("ocs/v2.php/cloud/user"), SimpleNetworkJob::UrlQuery{}, QNetworkRequest{}, this);
job->setAuthenticationJob(isAuthJob());
job->setTimeout(timeoutC);
QObject::connect(userJob, &JsonApiJob::finishedSignal, this, [userJob, this] {
userJob->setAuthenticationJob(isAuthJob());
userJob->setTimeout(timeoutC);
connect(userJob, &JsonApiJob::finishedSignal, this, [userJob, this] {
const auto userData = userJob->data().value(QStringLiteral("ocs")).toObject().value(QStringLiteral("data")).toObject();
const QString user = userData.value(QStringLiteral("id")).toString();
if (!user.isEmpty()) {
Expand Down
11 changes: 9 additions & 2 deletions src/libsync/creds/oauth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,16 @@ void OAuth::startAuthentication()
qCDebug(lcOauth) << "starting authentication";

// Listen on the socket to get a port which will be used in the redirect_uri
if (!_server.listen(QHostAddress::LocalHost)) {

for (const auto port : Theme::instance()->oauthPorts()) {
if (_server.listen(QHostAddress::LocalHost, port)) {
break;
}
qCDebug(lcOauth) << "Creating local server Port:" << port << "failed. Error:" << _server.errorString();
}
if (!_server.isListening()) {
qCDebug(lcOauth) << "server is not listening";
emit result(NotSupported, QString());
emit result(Error, {});
return;
}

Expand Down
6 changes: 6 additions & 0 deletions src/libsync/theme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,12 @@ QPair<QString, QString> Theme::oauthOverrideAuthUrl() const
return {};
}

QVector<quint16> Theme::oauthPorts() const
{
// zero means a random port
return {0};
}

QString Theme::openIdConnectScopes() const
{
return QStringLiteral("openid offline_access email profile");
Expand Down
5 changes: 5 additions & 0 deletions src/libsync/theme.h
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,11 @@ class OWNCLOUDSYNC_EXPORT Theme : public QObject
*/
virtual QPair<QString, QString> oauthOverrideAuthUrl() const;

/**
* List of ports to use for the local redirect server
*/
virtual QVector<quint16> oauthPorts() const;

/**
* Returns the required opeidconnect scopes
*/
Expand Down
81 changes: 59 additions & 22 deletions test/gui/shared/scripts/bdd_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import shutil
import urllib.request
import os
from urllib.parse import urlparse
from helpers.StacktraceHelper import getCoredumps, generateStacktrace
from helpers.SyncHelper import closeSocketConnection, clearWaitedAfterSync
from helpers.SpaceHelper import delete_project_spaces
Expand All @@ -32,6 +33,9 @@
)
from helpers.api.utils import url_join
from datetime import datetime
from pageObjects.Toolbar import Toolbar
from pageObjects.AccountSetting import AccountSetting
from pageObjects.AccountConnectionWizard import AccountConnectionWizard

# this will reset in every test suite
previousFailResultCount = 0
Expand Down Expand Up @@ -166,28 +170,8 @@ def hook(context):

pb.savev(os.path.join(directory, filename), "png", [], [])

# Detach (i.e. potentially terminate) all AUTs at the end of a scenario
for ctx in applicationContextList():
# get pid before detaching
pid = ctx.pid
ctx.detach()
wait_until_app_killed(pid)

# clean up config files
for config_file in os.listdir(get_config('clientConfigDir')):
os.unlink(os.path.join(get_config('clientConfigDir'), config_file))

# delete local files/folders
for filename in os.listdir(get_config('clientRootSyncPath')):
test.log("Deleting: " + filename)
file_path = os.path.join(get_config('clientRootSyncPath'), filename)
try:
if os.path.isfile(file_path) or os.path.islink(file_path):
os.unlink(file_path)
elif os.path.isdir(file_path):
shutil.rmtree(file_path)
except Exception as e:
test.log(f'Failed to delete{file_path}. Reason: {e}.')
# teardown accounts and configs
teardown_client()

# search coredumps after every test scenario
# CI pipeline might fail although all tests are passing
Expand Down Expand Up @@ -216,3 +200,56 @@ def hook(context):

previousFailResultCount = test.resultCount("fails")
previousErrorResultCount = test.resultCount("errors")


def teardown_client():
# Cleanup user accounts from UI for Windows platform
# It is not needed for Linux so skipping it in order to save CI time
if isWindows():
# remove account from UI
# In Windows, removing only config and sync folders won't help
# so to work around that, remove the account connection
close_open_dialogs()
server_host = urlparse(get_config('localBackendUrl')).netloc
accounts = Toolbar.get_accounts()
for account in accounts:
displayname = account.split('\n')[0]
Toolbar.openAccount(displayname, server_host)
AccountSetting.removeAccountConnection()
if accounts:
waitForObject(AccountConnectionWizard.SERVER_ADDRESS_BOX)

# Detach (i.e. potentially terminate) all AUTs at the end of a scenario
for ctx in applicationContextList():
# get pid before detaching
pid = ctx.pid
ctx.detach()
wait_until_app_killed(pid)

# clean up config files
shutil.rmtree(get_config('clientConfigDir'))

# delete test files/folders
for entry in os.scandir(get_config('clientRootSyncPath')):
test.log("Deleting: " + entry.name)
try:
if entry.is_file() or entry.is_symlink():
os.unlink(entry.path)
elif entry.is_dir():
shutil.rmtree(entry.path)
except Exception as e:
test.log(f'Failed to delete{entry.name}. Reason: {e}.')


def close_open_dialogs():
# close the current active dailog if it's not a main client window
while True:
active_window = QApplication.activeModalWidget()
if str(active_window) == "<null>":
break
test.log(f"Closing '{active_window.objectName}' window")
closed = active_window.close()
if not closed:
confirm_dialog = QApplication.activeModalWidget()
if confirm_dialog.visible:
clickButton(waitForObject(AccountSetting.CONFIRMATION_YES_BUTTON))
13 changes: 13 additions & 0 deletions test/gui/shared/scripts/helpers/FilesHelper.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import os
import re
import ctypes
from helpers.ConfigHelper import isWindows


def buildConflictedRegex(filename):
Expand Down Expand Up @@ -78,3 +80,14 @@ def get_size_in_bytes(size):
return size_num * (multiplier**3)

raise Exception("Invalid size: " + size)


def get_file_size_on_disk(resource_path):
file_size_high = ctypes.c_ulonglong(0)
if isWindows():
return ctypes.windll.kernel32.GetCompressedFileSizeW(
ctypes.c_wchar_p(resource_path), ctypes.pointer(file_size_high)
)
raise Exception(
"'get_file_size_on_disk' function is only supported for Windows OS."
)
Loading

0 comments on commit 612e416

Please sign in to comment.