diff --git a/src/core/slavebase.cpp b/src/core/slavebase.cpp --- a/src/core/slavebase.cpp +++ b/src/core/slavebase.cpp @@ -123,6 +123,7 @@ KIO::filesize_t totalSize; KRemoteEncoding *remotefile; enum { Idle, InsideMethod, FinishedCalled, ErrorCalled } m_state; + bool m_finalityCommand = true; // whether finished() or error() may/must be called QByteArray timeoutData; KPasswdServerClient *m_passwdServerClient; @@ -185,18 +186,34 @@ } } + bool finalState() const + { + return ((m_state == FinishedCalled) || (m_state == ErrorCalled)); + } + void verifyState(const char *cmdName) { - if ((m_state != FinishedCalled) && (m_state != ErrorCalled)) { - qCWarning(KIO_CORE) << cmdName << "did not call finished() or error()! Please fix the" << QCoreApplication::applicationName() << "KIO slave"; + Q_ASSERT_X(finalState(), + Q_FUNC_INFO, + qUtf8Printable(QStringLiteral("%1 did not call finished() or error()! Please fix the %2 KIO slave") + .arg(cmdName) + .arg(QCoreApplication::applicationName()))); + // Force the command into finished state. We'll not reach this for Debug builds + // that fail the assertion. For Releas builds we'll have made sure that the + // command is actually finished after the verfication regardless of what + // the slave did. + if (!finalState()) { + q->finished(); } } void verifyErrorFinishedNotCalled(const char *cmdName) { - if (m_state == FinishedCalled || m_state == ErrorCalled) { - qCWarning(KIO_CORE) << cmdName << "called finished() or error(), but it's not supposed to! Please fix the" << QCoreApplication::applicationName() << "KIO slave"; - } + Q_ASSERT_X(!finalState(), + Q_FUNC_INFO, + qUtf8Printable(QStringLiteral("%1 called finished() or error(), but it's not supposed to! Please fix the %2 KIO slave") + .arg(cmdName) + .arg(QCoreApplication::applicationName()))); } KPasswdServerClient *passwdServerClient() @@ -458,11 +475,22 @@ void SlaveBase::error(int _errid, const QString &_text) { + Q_ASSERT_X(d->m_finalityCommand, + Q_FUNC_INFO, + qUtf8Printable(QStringLiteral("error() was called, but it's not supposed to! Please fix the %2 KIO slave") + .arg(QCoreApplication::applicationName()))); + if (d->m_state == d->ErrorCalled) { - qCWarning(KIO_CORE) << "error() called twice! Please fix the" << QCoreApplication::applicationName() << "KIO slave"; + Q_ASSERT_X(false, + Q_FUNC_INFO, + qUtf8Printable(QStringLiteral("error() called twice! Please fix the %1 KIO slave") + .arg(QCoreApplication::applicationName()))); return; } else if (d->m_state == d->FinishedCalled) { - qCWarning(KIO_CORE) << "error() called after finished()! Please fix the" << QCoreApplication::applicationName() << "KIO slave"; + Q_ASSERT_X(false, + Q_FUNC_INFO, + qUtf8Printable(QStringLiteral("error() called after finished()! Please fix the %1 KIO slave") + .arg(QCoreApplication::applicationName()))); return; } @@ -502,11 +530,22 @@ d->pendingListEntries.clear(); } + Q_ASSERT_X(d->m_finalityCommand, + Q_FUNC_INFO, + qUtf8Printable(QStringLiteral("finished() was called, but it's not supposed to! Please fix the %2 KIO slave") + .arg(QCoreApplication::applicationName()))); + if (d->m_state == d->FinishedCalled) { - qCWarning(KIO_CORE) << "finished() called twice! Please fix the" << QCoreApplication::applicationName() << "KIO slave"; + Q_ASSERT_X(false, + Q_FUNC_INFO, + qUtf8Printable(QStringLiteral("finished() called twice! Please fix the %1 KIO slave") + .arg(QCoreApplication::applicationName()))); return; } else if (d->m_state == d->ErrorCalled) { - qCWarning(KIO_CORE) << "finished() called after error()! Please fix the" << QCoreApplication::applicationName() << "KIO slave"; + Q_ASSERT_X(false, + Q_FUNC_INFO, + qUtf8Printable(QStringLiteral("finished() called after error()! Please fix the %1 KIO slave") + .arg(QCoreApplication::applicationName()))); return; } @@ -1062,15 +1101,17 @@ QUrl url; int i; + d->m_finalityCommand = true; // default + switch (command) { case CMD_HOST: { QString passwd; QString host, user; quint16 port; stream >> host >> port >> user >> passwd; d->m_state = d->InsideMethod; + d->m_finalityCommand = false; setHost(host, port, user, passwd); - d->verifyErrorFinishedNotCalled("setHost()"); d->m_state = d->Idle; } break; case CMD_CONNECT: { @@ -1081,9 +1122,9 @@ } break; case CMD_SLAVE_STATUS: { d->m_state = d->InsideMethod; + d->m_finalityCommand = false; slave_status(); // TODO verify that the slave has called slaveStatus()? - d->verifyErrorFinishedNotCalled("slave_status()"); d->m_state = d->Idle; } break; case CMD_SLAVE_CONNECT: { @@ -1110,8 +1151,8 @@ } break; case CMD_REPARSECONFIGURATION: { d->m_state = d->InsideMethod; + d->m_finalityCommand = false; reparseConfiguration(); - d->verifyErrorFinishedNotCalled("reparseConfiguration()"); d->m_state = d->Idle; } break; case CMD_CONFIG: {