QNearFieldManager: extend tests

Extend the implementation of the manager emulator, and provide tests
to cover the implementation.
This patch also fixes the tst_qnearfieldtagtype* to prevent the
crashes when the matching target is not found.

Task-number: QTBUG-94037
Pick-to: 6.2
Change-Id: I32e5ed747a85d996e4f0f6f66b3321ddebfbdb26
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
This commit is contained in:
Ivan Solovev 2021-06-07 14:31:48 +02:00
parent ded6f0ad10
commit 661da19ebb
7 changed files with 153 additions and 36 deletions

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtNfc module of the Qt Toolkit.
@ -62,9 +62,31 @@ bool QNearFieldManagerPrivateImpl::isEnabled() const
return true;
}
bool QNearFieldManagerPrivateImpl::startTargetDetection(QNearFieldTarget::AccessMethod)
bool QNearFieldManagerPrivateImpl::isSupported(QNearFieldTarget::AccessMethod accessMethod) const
{
return true;
return accessMethod == QNearFieldTarget::NdefAccess
|| accessMethod == QNearFieldTarget::AnyAccess;
}
bool QNearFieldManagerPrivateImpl::startTargetDetection(QNearFieldTarget::AccessMethod accessMethod)
{
const bool supported = isSupported(accessMethod);
if (supported)
TagActivator::instance()->start();
return supported;
}
void QNearFieldManagerPrivateImpl::stopTargetDetection(const QString &message)
{
setUserInformation(message);
TagActivator::instance()->stop();
emit targetDetectionStopped();
}
void QNearFieldManagerPrivateImpl::setUserInformation(const QString &message)
{
emit userInformationChanged(message);
}
void QNearFieldManagerPrivateImpl::reset()

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtNfc module of the Qt Toolkit.
@ -72,10 +72,17 @@ public:
bool isEnabled() const override;
bool isSupported(QNearFieldTarget::AccessMethod accessMethod) const override;
bool startTargetDetection(QNearFieldTarget::AccessMethod accessMethod) override;
void stopTargetDetection(const QString &message) override;
void setUserInformation(const QString &message) override;
void reset();
signals:
void userInformationChanged(const QString &message);
private slots:
void tagActivated(TagBase *tag);
void tagDeactivated(TagBase *tag);

View File

@ -184,9 +184,7 @@ bool TagType2::waitForRequestCompleted(const QNearFieldTarget::RequestId &id, in
return QNearFieldTagType2::waitForRequestCompleted(id, msecs);
}
TagActivator::TagActivator()
: timerId(-1)
TagActivator::TagActivator() : QObject()
{
qRegisterMetaType<QNearFieldTarget::Error>();
}
@ -237,21 +235,38 @@ void TagActivator::initialize()
}
current = tagMap.end();
timerId = startTimer(1000);
}
void TagActivator::reset()
{
QMutexLocker locker(&tagMutex);
killTimer(timerId);
timerId = -1;
stopInternal();
qDeleteAll(tagMap.keys());
tagMap.clear();
}
void TagActivator::start()
{
QMutexLocker locker(&tagMutex);
timerId = startTimer(1000);
}
void TagActivator::stop()
{
QMutexLocker locker(&tagMutex);
stopInternal();
}
void TagActivator::stopInternal()
{
if (timerId != -1) {
killTimer(timerId);
timerId = -1;
}
}
TagActivator *TagActivator::instance()
{
return globalTagActivator();

View File

@ -108,6 +108,9 @@ public:
void initialize();
void reset();
void start();
void stop();
static TagActivator *instance();
protected:
@ -118,8 +121,10 @@ signals:
void tagDeactivated(TagBase *tag);
private:
void stopInternal();
QMap<TagBase *, bool>::Iterator current;
int timerId;
int timerId = -1;
};
QT_END_NAMESPACE

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtNfc module of the Qt Toolkit.
@ -52,6 +52,11 @@ public:
private slots:
void initTestCase();
void isSupported();
void isSupported_data();
void userInformation();
void targetDetected_data();
void targetDetected();
};
@ -72,27 +77,73 @@ void tst_QNearFieldManager::initTestCase()
QVERIFY(manager.isEnabled());
}
void tst_QNearFieldManager::isSupported()
{
QFETCH(QNearFieldTarget::AccessMethod, accessMethod);
QFETCH(bool, supported);
QNearFieldManagerPrivateImpl *emulatorBackend = new QNearFieldManagerPrivateImpl;
QNearFieldManager manager(emulatorBackend, nullptr);
QCOMPARE(manager.isSupported(accessMethod), supported);
}
void tst_QNearFieldManager::isSupported_data()
{
QTest::addColumn<QNearFieldTarget::AccessMethod>("accessMethod");
QTest::addColumn<bool>("supported");
QTest::newRow("UnknownAccess") << QNearFieldTarget::UnknownAccess << false;
QTest::newRow("NdefAccess") << QNearFieldTarget::NdefAccess << true;
QTest::newRow("TagTypeSpecificAccess") << QNearFieldTarget::TagTypeSpecificAccess << false;
QTest::newRow("AnyAccess") << QNearFieldTarget::AnyAccess << true;
}
void tst_QNearFieldManager::userInformation()
{
QNearFieldManagerPrivateImpl *emulatorBackend = new QNearFieldManagerPrivateImpl;
QNearFieldManager manager(emulatorBackend, nullptr);
QSignalSpy spy(emulatorBackend, &QNearFieldManagerPrivateImpl::userInformationChanged);
manager.startTargetDetection(QNearFieldTarget::AnyAccess);
const QString progressString("NFC target detection in progress");
manager.setUserInformation(progressString);
const QString errorString("Failed to detect NFC targets");
manager.stopTargetDetection(errorString);
QCOMPARE(spy.count(), 2);
QCOMPARE(spy.at(0).at(0).toString(), progressString);
QCOMPARE(spy.at(1).at(0).toString(), errorString);
}
void tst_QNearFieldManager::targetDetected_data()
{
QTest::addColumn<QNearFieldTarget::AccessMethod>("accessMethod");
QTest::addColumn<bool>("deleteTarget");
QTest::newRow("AnyTarget") << false;
QTest::newRow("NfcTagType1") << false;
QTest::newRow("Delete Target") << true;
QTest::newRow("UnknownAccess") << QNearFieldTarget::UnknownAccess << false;
QTest::newRow("NdefAccess, no delete") << QNearFieldTarget::NdefAccess << false;
QTest::newRow("AnyAccess, delete") << QNearFieldTarget::AnyAccess << true;
}
void tst_QNearFieldManager::targetDetected()
{
QFETCH(QNearFieldTarget::AccessMethod, accessMethod);
QFETCH(bool, deleteTarget);
QNearFieldManagerPrivateImpl *emulatorBackend = new QNearFieldManagerPrivateImpl;
QNearFieldManager manager(emulatorBackend, 0);
QNearFieldManager manager(emulatorBackend, nullptr);
QSignalSpy targetDetectedSpy(&manager, SIGNAL(targetDetected(QNearFieldTarget*)));
QSignalSpy targetLostSpy(&manager, SIGNAL(targetLost(QNearFieldTarget*)));
QSignalSpy targetDetectedSpy(&manager, &QNearFieldManager::targetDetected);
QSignalSpy targetLostSpy(&manager, &QNearFieldManager::targetLost);
QSignalSpy detectionStoppedSpy(&manager, &QNearFieldManager::targetDetectionStopped);
manager.startTargetDetection(QNearFieldTarget::UnknownAccess);
const bool started = manager.startTargetDetection(accessMethod);
if (started) {
QTRY_VERIFY(!targetDetectedSpy.isEmpty());
QNearFieldTarget *target = targetDetectedSpy.first().at(0).value<QNearFieldTarget *>();
@ -120,8 +171,11 @@ void tst_QNearFieldManager::targetDetected()
QTRY_VERIFY(targetLostSpy.isEmpty() && !targetDetectedSpy.isEmpty());
}
}
manager.stopTargetDetection();
QCOMPARE(detectionStoppedSpy.count(), 1);
}
QTEST_MAIN(tst_QNearFieldManager)

View File

@ -76,6 +76,7 @@ void tst_QNearFieldTagType1::init()
targetParent = new QObject();
TagActivator::instance()->initialize();
TagActivator::instance()->start();
}
void tst_QNearFieldTagType1::cleanup()
@ -104,6 +105,8 @@ void tst_QNearFieldTagType1::waitForMatchingTarget()
void tst_QNearFieldTagType1::staticMemoryModel()
{
waitForMatchingTarget();
if (QTest::currentTestFailed())
return;
QVERIFY(target->accessMethods() & QNearFieldTarget::TagTypeSpecificAccess);
@ -239,6 +242,8 @@ void tst_QNearFieldTagType1::dynamicMemoryModel()
QList<QByteArray> seenIds;
forever {
waitForMatchingTarget();
if (QTest::currentTestFailed())
return;
QNearFieldTarget::RequestId id = target->readIdentification();
QVERIFY(target->waitForRequestCompleted(id));
@ -368,6 +373,8 @@ void tst_QNearFieldTagType1::ndefMessages()
QByteArray firstId;
forever {
waitForMatchingTarget();
if (QTest::currentTestFailed())
return;
QNearFieldTarget::RequestId id = target->readIdentification();
QVERIFY(target->waitForRequestCompleted(id));

View File

@ -77,6 +77,7 @@ void tst_QNearFieldTagType2::init()
targetParent = new QObject();
TagActivator::instance()->initialize();
TagActivator::instance()->start();
}
void tst_QNearFieldTagType2::cleanup()
@ -105,6 +106,8 @@ void tst_QNearFieldTagType2::waitForMatchingTarget()
void tst_QNearFieldTagType2::staticMemoryModel()
{
waitForMatchingTarget();
if (QTest::currentTestFailed())
return;
QVERIFY(target->accessMethods() & QNearFieldTarget::TagTypeSpecificAccess);
@ -166,6 +169,8 @@ void tst_QNearFieldTagType2::dynamicMemoryModel()
QList<QByteArray> seenIds;
forever {
waitForMatchingTarget();
if (QTest::currentTestFailed())
return;
QVERIFY(target->accessMethods() & QNearFieldTarget::TagTypeSpecificAccess);
@ -267,6 +272,8 @@ void tst_QNearFieldTagType2::ndefMessages()
QByteArray firstId;
forever {
waitForMatchingTarget();
if (QTest::currentTestFailed())
return;
QNearFieldTarget::RequestId id = target->readBlock(0);
QVERIFY(target->waitForRequestCompleted(id));