D23579: WIP: port ftp slave to new error reporting system
David Faure
noreply at phabricator.kde.org
Sat Sep 21 04:50:54 BST 2019
dfaure requested changes to this revision.
dfaure added a comment.
This revision now requires changes to proceed.
Nice work!
INLINE COMMENTS
> ftptest.cpp:33
> +public:
> + QUrl url(const QString &path)
> + {
this method should be const
> ftptest.cpp:50
> + // works around the fact that kioslave would load the slave from the system
> + // as first choice instead of the one from teh build dir.
> + qputenv("QT_PLUGIN_PATH", QCoreApplication::applicationDirPath().toUtf8());
typo: teh -> the
> ftptest.cpp:53
> +
> + // Run ftpd to talk t.
> + QVERIFY(m_remoteDir.isValid());
"talk t" ? missing 'o'?
> ftptest.cpp:61
> + QVERIFY(m_daemonProc.waitForStarted());
> + QVERIFY(m_daemonProc.state() == QProcess::Running);
> + // Wait for the daemon to print its port. That tells us both where it's listening
QCOMPARE so we see the state if it fails
> ftptest.cpp:97
> + {
> + Q_ASSERT(m_daemonProc.state() == QProcess::Running);
> + }
QCOMPARE
> ftptest.cpp:114
> + job->setUiDelegate(nullptr);
> + QVERIFY(job->exec());
> + QCOMPARE(job->data(), data);
QVERIFY2(job->exec(), qUtf8Printable(job->errorString()));
> ftptest.cpp:167
> + job->setUiDelegate(nullptr);
> + QEXPECT_FAIL("", "Trying to write to an inacessible path fails.", Continue);
> + QVERIFY2(job->exec(), qUtf8Printable(job->errorString()));
QEXPECT_FAIL is for known bugs.
Here, what you want is
QVERIFY(!job->exec());
> ftptest.cpp:180
> + inaccessibleUrl.setPassword("password");
> + const QString remoteInaccesiblePath = m_remoteDir.path() + inaccessiblePath;
> + QVERIFY(QFile::copy(QFINDTESTDATA("ftp/testCopy1"),
missing a 's' in Inaccessible
I'm confused whether this test is about inaccessible path or something around resuming.
> ftptest.cpp:186
> + job->setUiDelegate(nullptr);
> + QEXPECT_FAIL("", "Trying to write with bad quot doesn't work.", Continue);
> + QVERIFY2(job->exec(), qUtf8Printable(job->errorString()));
what's bad quot?
Is this test about a bug, or the job failing is what we want?
> ftptest.cpp:206
> + job->setUiDelegate(nullptr);
> + QVERIFY(job->exec());
> + QCOMPARE(job->error(), 0);
I should ask for a clazy rule about QVERIFY(job->exec()) :-)
[same as above, QVERIFY2...]
> ftptest.cpp:217
> +
> +// FIXME: Actually BROKEN
> +
Now *that* is what QEXPECT_FAIL is about :-)
You can re-enable the code, and use QEXPECT_FAIL above the failing QVERIFY or QCOMPARE.
> ftp.cpp:671
> + if (!result.success) {
> + return result;
> + }
I don't think we want to return on failure here.
If the server doesn't support this command, we might as well try proceeding.
That's why the old code actually ignored errors here.
> ftp.cpp:696
> qCDebug(KIO_FTP) << "Searching for pwd";
> - if (!ftpSendCmd(QByteArrayLiteral("PWD")) || (m_iRespType != 2)) {
> + result = ftpSendCmd(QByteArrayLiteral("PWD"));
> + if (!result.success || (m_iRespType != 2)) {
The reuse of the `result` var irks me a bit.
const vars rock :-)
Would it be a bad idea to make Result implicitly convertible to bool, so you can keep doing this inside the if? ` if (!ftpSendCmd(QByteArrayLiteral("PWD")) || (m_iRespType != 2)) {` would still work fine then.
This would simplify all cases where we test for failures, but ignore the actual error message on failure (because we'll provide a more high-level one, like here). In other cases, we indeed need a result var.
> ftp.cpp:801
> + const auto result = ftpOpenConnection(LoginMode::Defered);
> +#pragma message "we ignore success of the new command its unclear if that is intentional"
> + if (result.success) {
Oh... it's a recursive call... wow, tricky.
Yeah, that means this method returns false even if the nested method managed to login. Very confusing, and probably wrong...
> ftp.cpp:828
> }
> - return false;
> + return Result::fail(); // else we don't know what went wrong
> }
I think this is all quite redundant.
openConnection() sets m_bLoggedOn to true if it succeeds, and to false if it fails.
So the ret val from openConnection and m_bLoggedOn are the same thing.
It makes little sense to test both independently and then even have a third case of failure in this line.
It's all the same, I suggest to simplify this.
I think this can all be simplified to
if (!openResult.success) {
if (m_control) { // ...
closeConnection();
}
return openResult; // or Result::fail(ERR_CANNOT_LOGIN, m_host), if the error code from openResult is no good
}
> ftp.cpp:1120
> errormessage = m_host;
> - return false;
> + return Result::fail();
> }
why not use errorcode and errormessage here?
or in fact just removing that line, so that it goes to the correct `return Result::fail(errorcode...)` below.
I believe this was a bug in the orig code, setting two local vars and then returning false is nonsense, the `return false` shouldn't have been there.
> ftp.cpp:1213
> if (!ftpFolder(src.left(pos + 1), false)) {
> - return false;
> + return Result::fail();
> }
`ERR_CANNOT_ENTER_DIRECTORY, src`
> ftp.cpp:1490
> }
> - Ftp::stat(linkURL);
> - return;
> +#pragma message "this used to return nothing and ignored the stat what gives"
> + return FtpInternal::stat(linkURL);
That's because it was a recursive call, so it left the callee in charge of emitting error/finished.
Not doing it here again was actually correct.
Now that error codes are returned, your change is correct, you can remove the pragma.
> ftp.cpp:1602
> - // Servers running with Turkish locale having problems converting 'i' letter to upper case.
> - // So we send correct upper case command as last resort.
> - if (!ftpOpenCommand("LIST -la", QString(), 'I', ERR_CANNOT_ENTER_DIRECTORY)) {
What happened to those two lines of comments? Can I suggest to keep them?
> ftp.cpp:1880
> + if (!result.success) {
> +#pragma message "was server error here"
> + return result;
Wasn't that just a way to propagate the error from the low-level method to this method? Your new mechanism replaces that, no?
> ftp.cpp:1908
> qCWarning(KIO_FTP) << "Can't open for reading";
> - return statusServerError;
> +#pragma message "was server error here"
> + return result;
Same as above: why do we still need this distinction? Is this enum useful?
> ftp.cpp:1991
> + } else if ((writeError = WriteToFile(iCopyFile, buffer, n)) != 0) {
> +#pragma message "we cannot construct the final error here because we do not know what the target fiel path is"
> + return Result::fail(writeError, QString(), StatusCode::ClientError);
Yep. Pass sCopyFile as argument, when ftpCopyGet calls ftpGet, just like what happens with iCopyFile.
> ftp.cpp:2032
> qCDebug(KIO_FTP) << "finished";
> - finished();
> + finished2(Q_FUNC_INFO);
> qCDebug(KIO_FTP) << "after finished";
?
> ftp.cpp:2085
>
> -Ftp::StatusCode Ftp::ftpPut(int &iError, int iCopyFile, const QUrl &dest_url,
> - int permissions, KIO::JobFlags flags)
> +#pragma message "ierrror should be moot with results"
> +Result FtpInternal::ftpPut(int iCopyFile, const QUrl &dest_url,
outdated warning?
> ftp.cpp:2169
> + if (!storResult.success) {
> +#pragma message "re-constructing failure"
> + return Result::fail(storResult.error, storResult.errorString, StatusCode::ServerError);
because of the useless enum? ;)
> ftp.cpp:2193
> if (result < 0) {
> - iError = ERR_CANNOT_WRITE;
> +#pragma message "isnt this cannot read we fail to read the input file here no"
> + writeError = ERR_CANNOT_WRITE;
yeah, feel free to change it.
> ftp.cpp:2341
> if (m_iRespType != 2) {
> - if (bReportError) {
> - error(ERR_CANNOT_ENTER_DIRECTORY, path);
> - }
> +#pragma message "reporterror has been broken not sure what to do with it"
> +// if (bReportError) {
Well, that's part of your refactoring. It was used to decide if a method should emit error on failure or just return false. It was part of the big mess that you're cleaning up. Kill bReportError completely.
> ftp.cpp:2363
>
> + Result result = Result::pass();
> if (bSrcLocal && !bDestLocal) { // File -> Ftp
optimistic but useless initializations, all code paths set (or ignore) result.
> ftp.cpp:2409
> #else
> return ftpPut(iError, iCopyFile, url, permissions, flags | KIO::Resume);
> #endif
probably needs the same treatment, i.e. removing iError?
(ifdef'ed out code)
> ftp.cpp:2488
> + result = Result::fail(ERR_CANNOT_WRITE, StatusCode::ClientError);
> +#pragma message "shouldnt we return here"
> }
no, we keep going in order to delete the .part file
> ftp.cpp:2596
> qCDebug(KIO_FTP) << "user canceled proxy authentication, or communication error.";
> - error(errorCode, m_proxyURL.host());
> +#pragma message "problem this is a slot so we cant return a result up the call chain maybe do it like errno or something"
> +// error(errorCode, m_proxyURL.host());
Yes, clearly. But the question is where to check it.
Hmm, how does this method even get called, without an event loop? From `m_control->waitForReadyRead`, maybe?
The old code was broken here, it would for sure emit error+error or error+finished, since the main code had no idea that this slot emitted error already.
Hmm. Shouldn't we do this connect *before* the waitForConnected in Ftp::synchronousConnectToHost? If a proxy exists, it will surely act at connection time?
And then it becomes easier, the place where to check the errno-like member is just after the call to Ftp::synchronousConnectToHost...
> ftp.cpp:2706
> +{
> + finalize(d->openConnection());
> +}
This looks wrong. openConnection() should emit connected() or error(), but never finished().
> ftp.cpp:2766
> +{
> + qDebug() << result;
> + if (!result.success) {
remember to clean up the qDebug()s before the final version
> ftp.h:70
> +struct Result {
> + bool success;
> + int error;
I think you can make all members const?
(This will prevent bypassing the "factory methods"...)
> ftp.h:95
> +private:
> + Result(bool s, int e, const QString &errString, StatusCode code)
> + : success(s)
This class is an aggregate, so you could probably remove this ctor and use `Result{...}` syntax in the above three methods.
> ftp.h:156
> +
> + void finished()
> + {
Does this method serve any purpose?
> ftp.h:340
>
> - void ftpShortStatAnswer(const QString &filename, bool isDir);
> + void ftpShortStatAnswer(const QString &filename, bool isDir) Q_REQUIRED_RESULT;
>
Q_REQUIRED_RESULT on a method returning void??
REPOSITORY
R241 KIO
REVISION DETAIL
https://phabricator.kde.org/D23579
To: sitter, dfaure
Cc: dfaure, kde-frameworks-devel, LeGast00n, GB_2, michaelh, ngraham, bruns
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.kde.org/pipermail/kde-frameworks-devel/attachments/20190921/7a8fc5d9/attachment-0001.html>
More information about the Kde-frameworks-devel
mailing list