Revision control
Copy as Markdown
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <qndefrecord.h>
#include <qndefmessage.h>
#include <qndefnfctextrecord.h>
#include <qndefnfcurirecord.h>
QT_USE_NAMESPACE
Q_DECLARE_METATYPE(QNdefRecord)
class tst_QNdefMessage : public QObject
{
Q_OBJECT
public:
tst_QNdefMessage();
~tst_QNdefMessage();
private slots:
void equality();
void equality_data();
void parseSingleRecordMessage_data();
void parseSingleRecordMessage();
void parseCorruptedMessage();
void parseCorruptedMessage_data();
void parseComplexMessage();
};
tst_QNdefMessage::tst_QNdefMessage()
{
}
tst_QNdefMessage::~tst_QNdefMessage()
{
}
void tst_QNdefMessage::equality()
{
QFETCH(QNdefMessage, lhs);
QFETCH(QNdefMessage, rhs);
QFETCH(bool, result);
QCOMPARE(lhs == rhs, result);
QCOMPARE(rhs == lhs, result);
}
void tst_QNdefMessage::equality_data()
{
QTest::addColumn<QNdefMessage>("lhs");
QTest::addColumn<QNdefMessage>("rhs");
QTest::addColumn<bool>("result");
QTest::newRow("empty vs empty") << QNdefMessage() << QNdefMessage() << true;
{
QNdefRecord rec;
rec.setTypeNameFormat(QNdefRecord::Empty);
QNdefMessage message;
message.push_back(rec);
QTest::newRow("empty vs empty record") << QNdefMessage() << message << true;
}
{
QNdefMessage message;
message.push_back(QNdefNfcTextRecord());
QTest::newRow("empty vs non-empty record") << QNdefMessage() << message << false;
}
{
QNdefMessage lhs;
lhs.push_back(QNdefNfcTextRecord());
QNdefMessage rhs;
rhs.push_back(QNdefNfcUriRecord());
QTest::newRow("different records") << lhs << rhs << false;
}
{
QNdefMessage lhs;
lhs.push_back(QNdefNfcTextRecord());
lhs.push_back(QNdefNfcUriRecord());
QNdefMessage rhs;
rhs.push_back(QNdefNfcUriRecord());
QTest::newRow("different amount of records") << lhs << rhs << false;
}
{
QNdefMessage lhs;
lhs.push_back(QNdefNfcTextRecord());
lhs.push_back(QNdefNfcUriRecord());
QNdefMessage rhs;
rhs.push_back(QNdefNfcUriRecord());
rhs.push_back(QNdefNfcTextRecord());
QTest::newRow("same records, different order") << lhs << rhs << false;
}
{
QNdefMessage lhs;
lhs.push_back(QNdefNfcTextRecord());
lhs.push_back(QNdefNfcUriRecord());
QNdefMessage rhs;
rhs.push_back(QNdefNfcTextRecord());
rhs.push_back(QNdefNfcUriRecord());
QTest::newRow("same records, same order") << lhs << rhs << true;
}
}
void tst_QNdefMessage::parseSingleRecordMessage_data()
{
QTest::addColumn<QByteArray>("data");
QTest::addColumn<QNdefMessage>("message");
QTest::addColumn<QVariantList>("expectedData");
// empty message
{
QByteArray data;
data.append(char(0xc0)); // MB=1, ME=1
data.append(char(0)); // TYPE LENGTH
data.append(char(0)); // PAYLOAD LENGTH 3
data.append(char(0)); // PAYLOAD LENGTH 2
data.append(char(0)); // PAYLOAD LENGTH 1
data.append(char(0)); // PAYLOAD LENGTH 0
QTest::newRow("empty") << data << QNdefMessage() << QVariantList();
QNdefRecord record;
record.setTypeNameFormat(QNdefRecord::Empty);
QTest::newRow("empty record") << data
<< QNdefMessage(record)
<< QVariantList();
}
// empty short message
{
QByteArray data;
data.append(char(0xd0)); // MB=1, ME=1, SR=1
data.append(char(0)); // TYPE LENGTH
data.append(char(0)); // PAYLOAD LENGTH
QTest::newRow("empty") << data << QNdefMessage() << QVariantList();
QNdefRecord record;
record.setTypeNameFormat(QNdefRecord::Empty);
QTest::newRow("empty record") << data
<< QNdefMessage(record)
<< QVariantList();
}
// unknown message
{
QByteArray type("type");
QByteArray id("id");
QByteArray payload("payload");
QByteArray data;
data.append(char(0xcd)); // MB=1, ME=1, IL=1, TNF=5
data.append(char(type.size())); // TYPE LENGTH
data.append(char((payload.size() >> 24) & 0xff)); // PAYLOAD LENGTH 3
data.append(char((payload.size() >> 16) & 0xff)); // PAYLOAD LENGTH 2
data.append(char((payload.size() >> 8) & 0xff)); // PAYLOAD LENGTH 1
data.append(char((payload.size() >> 0) & 0xff)); // PAYLOAD LENGTH 0
data.append(char(id.size())); // ID LENGTH
data.append(type);
data.append(id);
data.append(payload);
QNdefRecord record;
record.setTypeNameFormat(QNdefRecord::Unknown);
record.setType(type);
record.setId(id);
record.setPayload(payload);
QList<QNdefRecord> recordList;
recordList.append(record);
QTest::newRow("unknown") << data << QNdefMessage(recordList) << QVariantList();
}
// chunked message
{
QByteArray type("type");
QByteArray id("id");
QByteArray payload("payload");
QByteArray data;
data.append(char(0xbd)); // MB=1, CF=1, SR=1, IL=1, TNF=5
data.append(char(type.size())); // TYPE LENGTH
data.append(char(1)); // PAYLOAD LENGTH
data.append(char(id.size())); // ID LENGTH
data.append(type); // TYPE
data.append(id); // ID
data.append(payload.at(0)); // PAYLOAD[0]
for (int i = 1; i < payload.size() - 1; ++i) {
data.append(char(0x36)); // CF=1, SR=1, TNF=6
data.append(char(0)); // TYPE LENGTH
data.append(char(1)); // PAYLOAD LENGTH
data.append(payload.at(i)); // PAYLOAD[i]
}
data.append(char(0x56)); // ME=1, SR=1, TNF=6
data.append(char(0)); // TYPE LENGTH
data.append(char(1)); // PAYLOAD LENGTH
data.append(payload.at(payload.size() - 1)); // PAYLOAD[length - 1]
QNdefRecord record;
record.setTypeNameFormat(QNdefRecord::Unknown);
record.setType(type);
record.setId(id);
record.setPayload(payload);
QList<QNdefRecord> recordList;
recordList.append(record);
QTest::newRow("chunked") << data << QNdefMessage(recordList) << QVariantList();
const QByteArray recordContent = record.type() + record.id()
+ record.payload();
QCOMPARE(recordContent, QByteArray::fromHex(QByteArray("7479706569647061796c6f6164")));
}
// NFC-RTD Text
{
QByteArray type("T");
QByteArray payload;
payload.append(char(0x02)); // UTF-8, 2 byte language code
payload.append("en");
payload.append("Test String");
QByteArray data;
data.append(char(0xc1)); // MB=1, ME=1, IL=0, TNF=1
data.append(char(type.size())); // TYPE LENGTH
data.append(char((payload.size() >> 24) & 0xff)); // PAYLOAD LENGTH 3
data.append(char((payload.size() >> 16) & 0xff)); // PAYLOAD LENGTH 2
data.append(char((payload.size() >> 8) & 0xff)); // PAYLOAD LENGTH 1
data.append(char((payload.size() >> 0) & 0xff)); // PAYLOAD LENGTH 0
data.append(type);
data.append(payload);
QNdefRecord record;
record.setTypeNameFormat(QNdefRecord::NfcRtd);
record.setType("T");
record.setPayload("\002enTest String");
QList<QNdefRecord> recordList;
recordList.append(record);
QTest::newRow("nfc-rtd text") << data << QNdefMessage(recordList)
<< (QVariantList() << QStringLiteral("Test String")
<< QStringLiteral("en"));
const QByteArray recordContent = record.type() + record.id()
+ record.payload();
QCOMPARE(recordContent,
QByteArray::fromHex(QByteArray("5402656e5465737420537472696e67")));
}
// NFC-RTD Text
{
QByteArray type("T");
QByteArray payload;
payload.append(char(0x02)); // UTF-8, 2 byte language code
payload.append("ja");
payload.append(QByteArray::fromHex("e38386e382b9e38388e69687e5ad97e58897"));
QByteArray data;
data.append(char(0xc1)); // MB=1, ME=1, IL=0, TNF=1
data.append(char(type.size())); // TYPE LENGTH
data.append(char((payload.size() >> 24) & 0xff)); // PAYLOAD LENGTH 3
data.append(char((payload.size() >> 16) & 0xff)); // PAYLOAD LENGTH 2
data.append(char((payload.size() >> 8) & 0xff)); // PAYLOAD LENGTH 1
data.append(char((payload.size() >> 0) & 0xff)); // PAYLOAD LENGTH 0
data.append(type);
data.append(payload);
QNdefRecord record;
record.setTypeNameFormat(QNdefRecord::NfcRtd);
record.setType("T");
record.setPayload("\002ja" + QByteArray::fromHex("e38386e382b9e38388e69687e5ad97e58897"));
QList<QNdefRecord> recordList;
recordList.append(record);
QTest::newRow("nfc-rtd text ja")
<< data << QNdefMessage(recordList)
<< (QVariantList() << QString::fromUtf8("\343\203\206\343\202\271\343\203\210\346\226"
"\207\345\255\227\345\210\227")
<< QStringLiteral("ja"));
const QByteArray recordContent = record.type() + record.id()
+ record.payload();
QCOMPARE(recordContent,
QByteArray::fromHex(QByteArray("54026a61e38386e382b9e38388e69687e5ad97e58897")));
}
// NFC-RTD URI
{
QByteArray type("U");
QByteArray payload;
payload.append(char(0x00));
QByteArray data;
data.append(char(0xc1));
data.append(char(type.size()));
data.append(char((payload.size() >> 24) & 0xff)); // PAYLOAD LENGTH 3
data.append(char((payload.size() >> 16) & 0xff)); // PAYLOAD LENGTH 2
data.append(char((payload.size() >> 8) & 0xff)); // PAYLOAD LENGTH 1
data.append(char((payload.size() >> 0) & 0xff)); // PAYLOAD LENGTH 0
data.append(type);
data.append(payload);
QNdefRecord record;
record.setTypeNameFormat(QNdefRecord::NfcRtd);
record.setType("U");
QList<QNdefRecord> recordList;
recordList.append(record);
<< data << QNdefMessage(recordList)
const QByteArray recordContent = record.type() + record.id()
+ record.payload();
QCOMPARE(recordContent,
QByteArray::fromHex(QByteArray("5500687474703a2f2f71742d70726f6a6563742e6f72672f")));
}
// NFC-RTD URI
{
QByteArray type("U");
QByteArray payload;
payload.append(char(0x03));
payload.append("qt-project.org/");
QByteArray data;
data.append(char(0xc1));
data.append(char(type.size()));
data.append(char((payload.size() >> 24) & 0xff)); // PAYLOAD LENGTH 3
data.append(char((payload.size() >> 16) & 0xff)); // PAYLOAD LENGTH 2
data.append(char((payload.size() >> 8) & 0xff)); // PAYLOAD LENGTH 1
data.append(char((payload.size() >> 0) & 0xff)); // PAYLOAD LENGTH 0
data.append(type);
data.append(payload);
QNdefRecord record;
record.setTypeNameFormat(QNdefRecord::NfcRtd);
record.setType("U");
record.setPayload(QByteArray("\003qt-project.org/", 16));
QList<QNdefRecord> recordList;
recordList.append(record);
<< data << QNdefMessage(recordList)
const QByteArray recordContent = record.type() + record.id()
+ record.payload();
QCOMPARE(recordContent,
QByteArray::fromHex(QByteArray("550371742d70726f6a6563742e6f72672f")));
}
// NFC-RTD URI
{
QByteArray type("U");
QByteArray payload;
payload.append(char(0x05));
payload.append("+1234567890");
QByteArray data;
data.append(char(0xc1));
data.append(char(type.size()));
data.append(char((payload.size() >> 24) & 0xff)); // PAYLOAD LENGTH 3
data.append(char((payload.size() >> 16) & 0xff)); // PAYLOAD LENGTH 2
data.append(char((payload.size() >> 8) & 0xff)); // PAYLOAD LENGTH 1
data.append(char((payload.size() >> 0) & 0xff)); // PAYLOAD LENGTH 0
data.append(type);
data.append(payload);
QNdefRecord record;
record.setTypeNameFormat(QNdefRecord::NfcRtd);
record.setType("U");
record.setPayload(QByteArray("\005+1234567890", 12));
QList<QNdefRecord> recordList;
recordList.append(record);
QTest::newRow("nfc-rtd uri tel:+1234567890")
<< data << QNdefMessage(recordList)
<< (QVariantList() << QUrl(QStringLiteral("tel:+1234567890")));
const QByteArray recordContent = record.type() + record.id()
+ record.payload();
QCOMPARE(recordContent,
QByteArray::fromHex(QByteArray("55052b31323334353637383930")));
}
// Chunk payload - the NFC-RTD URI split into 3 chunks
{
const QByteArray type("U");
const QByteArray id("test");
QByteArray payload1;
payload1.append(char(0x05));
payload1.append("+123");
const QByteArray payload2("456");
const QByteArray payload3("7890");
QByteArray data;
data.append(char(0xB9)); // MB=1, ME=0, CF=1, SR=1, IL=1, TNF=1 (NFC-RTD)
data.append(type.size());
data.append(payload1.size() & 0xff); // length fits into 1 byte
data.append(id.size());
data.append(type);
data.append(id);
data.append(payload1);
data.append(char(0x36)); // MB=0, ME=0, CF=1, SR=1, IL=0, TNF=6 (Unchanged)
data.append(char(0x00));
data.append(payload2.size());
data.append(payload2);
data.append(char(0x56)); // MB=0, ME=1, CF=0, SR=1, IL=0, TNF=6 (Unchanged)
data.append(char(0x00));
data.append(payload3.size());
data.append(payload3);
QNdefRecord record;
record.setTypeNameFormat(QNdefRecord::NfcRtd);
record.setType(type);
record.setId(id);
record.setPayload(QByteArray("\005+1234567890", 12));
QList<QNdefRecord> recordList;
recordList.append(record);
QTest::newRow("chunk payloads nfc-rtd uri tel:+1234567890")
<< data << QNdefMessage(recordList)
<< (QVariantList() << QUrl(QStringLiteral("tel:+1234567890")));
}
// Truncated message
{
QByteArray type("U");
QByteArray id("Test ID");
QByteArray payload;
payload.append(char(0x00));
QByteArray data;
data.append(char(0xc9)); // MB=1, ME=1, IL=1
QTest::newRow("truncated 1") << data << QNdefMessage() << QVariantList();
data.append(char(type.size())); // TYPE LENGTH
QTest::newRow("truncated 2") << data << QNdefMessage() << QVariantList();
data.append(char((payload.size() >> 24) & 0xff)); // PAYLOAD LENGTH 3
QTest::newRow("truncated 3") << data << QNdefMessage() << QVariantList();
data.append(char((payload.size() >> 16) & 0xff)); // PAYLOAD LENGTH 2
QTest::newRow("truncated 4") << data << QNdefMessage() << QVariantList();
data.append(char((payload.size() >> 8) & 0xff)); // PAYLOAD LENGTH 1
QTest::newRow("truncated 5") << data << QNdefMessage() << QVariantList();
data.append(char((payload.size() >> 0) & 0xff)); // PAYLOAD LENGTH 0
QTest::newRow("truncated 6") << data << QNdefMessage() << QVariantList();
data.append(char(id.size())); // ID LENGTH
QTest::newRow("truncated 7") << data << QNdefMessage() << QVariantList();
data.append(type);
QTest::newRow("truncated 8") << data << QNdefMessage() << QVariantList();
data.append(id);
QTest::newRow("truncated 9") << data << QNdefMessage() << QVariantList();
payload.chop(1);
data.append(payload);
QTest::newRow("truncated 10") << data << QNdefMessage() << QVariantList();
}
// Chunk payload - the NFC-RTD URI split into 4 chunks, one chunk in the
// middle has length == 0
{
const QByteArray type("U");
const QByteArray id("test");
QByteArray payload1;
payload1.append(char(0x05));
payload1.append("+123");
const QByteArray payload2("456");
// payload 3 is empty
const QByteArray payload4("7890");
QByteArray data;
data.append(char(0xB9)); // MB=1, ME=0, CF=1, SR=1, IL=1, TNF=1 (NFC-RTD)
data.append(type.size());
data.append(payload1.size() & 0xff); // length fits into 1 byte
data.append(id.size());
data.append(type);
data.append(id);
data.append(payload1);
data.append(char(0x36)); // MB=0, ME=0, CF=1, SR=1, IL=0, TNF=6 (Unchanged)
data.append(char(0x00));
data.append(payload2.size());
data.append(payload2);
data.append(char(0x36)); // MB=0, ME=0, CF=1, SR=1, IL=0, TNF=6 (Unchanged)
data.append(char(0x00));
data.append(char(0x00)); // PAYLOAD_LENGTH=0
data.append(char(0x56)); // MB=0, ME=1, CF=0, SR=1, IL=0, TNF=6 (Unchanged)
data.append(char(0x00));
data.append(payload4.size());
data.append(payload4);
QNdefRecord record;
record.setTypeNameFormat(QNdefRecord::NfcRtd);
record.setType(type);
record.setId(id);
record.setPayload(QByteArray("\005+1234567890", 12));
QList<QNdefRecord> recordList;
recordList.append(record);
QTest::newRow("4 chunk payloads with chunk 2 empty")
<< data << QNdefMessage(recordList)
<< (QVariantList() << QUrl(QStringLiteral("tel:+1234567890")));
}
// Chunk payload - the NFC-RTD URI split into 4 chunks, last chunk has
// length == 0
{
const QByteArray type("U");
const QByteArray id("test");
QByteArray payload1;
payload1.append(char(0x05));
payload1.append("+123");
const QByteArray payload2("456");
const QByteArray payload3("7890");
QByteArray data;
data.append(char(0xB9)); // MB=1, ME=0, CF=1, SR=1, IL=1, TNF=1 (NFC-RTD)
data.append(type.size());
data.append(payload1.size() & 0xff); // length fits into 1 byte
data.append(id.size());
data.append(type);
data.append(id);
data.append(payload1);
data.append(char(0x36)); // MB=0, ME=0, CF=1, SR=1, IL=0, TNF=6 (Unchanged)
data.append(char(0x00));
data.append(payload2.size());
data.append(payload2);
data.append(char(0x36)); // MB=0, ME=0, CF=1, SR=1, IL=0, TNF=6 (Unchanged)
data.append(char(0x00));
data.append(payload3.size());
data.append(payload3);
data.append(char(0x56)); // MB=0, ME=1, CF=0, SR=1, IL=0, TNF=6 (Unchanged)
data.append(char(0x00));
data.append(char(0x00)); // PAYLOAD_LENGTH=0
QNdefRecord record;
record.setTypeNameFormat(QNdefRecord::NfcRtd);
record.setType(type);
record.setId(id);
record.setPayload(QByteArray("\005+1234567890", 12));
QList<QNdefRecord> recordList;
recordList.append(record);
QTest::newRow("4 chunk payloads with last chunk empty")
<< data << QNdefMessage(recordList)
<< (QVariantList() << QUrl(QStringLiteral("tel:+1234567890")));
}
}
void tst_QNdefMessage::parseSingleRecordMessage()
{
QFETCH(QByteArray, data);
QFETCH(QNdefMessage, message);
QFETCH(QVariantList, expectedData);
if (QByteArray(QTest::currentDataTag()).startsWith("truncated "))
QTest::ignoreMessage(QtWarningMsg, "Unexpected end of message");
QNdefMessage parsedMessage = QNdefMessage::fromByteArray(data);
QVERIFY(parsedMessage == message);
QVERIFY(message == parsedMessage);
QNdefMessage reparsedMessage = QNdefMessage::fromByteArray(message.toByteArray());
QVERIFY(message == reparsedMessage);
QVERIFY(reparsedMessage == message);
for (qsizetype i = 0; i < message.size(); ++i) {
const QNdefRecord &record = message.at(i);
const QNdefRecord &parsedRecord = parsedMessage.at(i);
QCOMPARE(record.typeNameFormat(), parsedRecord.typeNameFormat());
QCOMPARE(record.type(), parsedRecord.type());
QCOMPARE(record.id(), parsedRecord.id());
QCOMPARE(record.payload(), parsedRecord.payload());
QCOMPARE(record.isEmpty(), parsedRecord.isEmpty());
if (record.isRecordType<QNdefNfcTextRecord>()) {
QNdefNfcTextRecord textRecord(record);
QNdefNfcTextRecord parsedTextRecord(parsedRecord);
QCOMPARE(textRecord.text(), parsedTextRecord.text());
QCOMPARE(textRecord.locale(), parsedTextRecord.locale());
if (expectedData.size() == 2) {
QCOMPARE(parsedTextRecord.text(), expectedData.at(0).toString());
QCOMPARE(parsedTextRecord.locale(), expectedData.at(1).toString());
}
} else if (record.isRecordType<QNdefNfcUriRecord>()) {
QNdefNfcUriRecord uriRecord(record);
QNdefNfcUriRecord parsedUriRecord(parsedRecord);
QCOMPARE(uriRecord.uri(), parsedUriRecord.uri());
if (expectedData.size() == 1)
QCOMPARE(parsedUriRecord.uri(), expectedData.at(0).toUrl());
} else if (record.isRecordType<QNdefRecord>()) {
QVERIFY(record.isEmpty());
}
}
}
void tst_QNdefMessage::parseCorruptedMessage()
{
// This test is needed to check that all the potential errors in the
// input data are handled correctly.
QFETCH(QByteArray, data);
QFETCH(QByteArray, warningMessage);
if (!warningMessage.isEmpty())
QTest::ignoreMessage(QtWarningMsg, warningMessage.constData());
QNdefMessage parsedMessage = QNdefMessage::fromByteArray(data);
// corrupted data always results in an empty message
QVERIFY(parsedMessage.isEmpty());
}
void tst_QNdefMessage::parseCorruptedMessage_data()
{
QTest::addColumn<QByteArray>("data");
QTest::addColumn<QByteArray>("warningMessage");
{
QByteArray data;
data.append(char(0x50)); // MB=0, ME=1, SR=1
data.append(char(0)); // TYPE LENGTH
data.append(char(0)); // PAYLOAD LENGTH
const QByteArray warningMsg = "Haven't got message begin yet";
QTest::newRow("No message begin") << data << warningMsg;
}
{
QByteArray data;
data.append(char(0x90)); // MB=1, ME=0, SR=1
data.append(char(0)); // TYPE LENGTH
data.append(char(0)); // PAYLOAD LENGTH
const QByteArray warningMsg = "Malformed NDEF Message, missing begin or end";
QTest::newRow("No message end") << data << warningMsg;
}
{
QByteArray data;
data.append(char(0x90)); // MB=1, ME=0, SR=1
data.append(char(0)); // TYPE LENGTH
data.append(char(0)); // PAYLOAD LENGTH
data.append(char(0xd0)); // MB=1, ME=1, SR=1
data.append(char(0)); // TYPE LENGTH
data.append(char(0)); // PAYLOAD LENGTH
const QByteArray warningMsg = "Got message begin but already parsed some records";
QTest::newRow("Multiple message begin") << data << warningMsg;
}
{
QByteArray data;
data.append(char(0xB1)); // MB=1, ME=0, CF=1, SR=1, IL=0, TNF=1 (NFC-RTD)
data.append(char(0x01)); // type length
data.append(char(0x01)); // payload length
data.append('U'); // type
data.append('a'); // payload
data.append(char(0x76)); // MB=0, ME=1 (incorrect), CF=1, SR=1, IL=0, TNF=6 (Unchanged)
data.append(char(0x00)); // type length
data.append(char(0x01)); // payload length
data.append('b'); // payload
data.append(char(0x56)); // MB=0, ME=1, CF=0, SR=1, IL=0, TNF=6 (Unchanged)
data.append(char(0x00)); // type length
data.append(char(0x01)); // payload length
data.append('c'); // payload
const QByteArray warningMsg = "Got message end but already parsed final record";
QTest::newRow("Multiple message end") << data << warningMsg;
}
{
QByteArray data;
data.append(char(0xB1)); // MB=1, ME=0, CF=1, SR=1, IL=0, TNF=1 (NFC-RTD)
data.append(char(0x01)); // type length
data.append(char(0x01)); // payload length
data.append('U'); // type
data.append('a'); // payload
data.append(char(0x36)); // MB=0, ME=0, CF=1, SR=1, IL=0, TNF=6 (Unchanged)
data.append(char(0x00)); // type length
data.append(char(0x01)); // payload length
data.append('b'); // payload
data.append(char(0x51)); // MB=0, ME=1, CF=0, SR=1, IL=0, TNF=1 (NFC-RTD - incorrect)
data.append(char(0x00)); // type length
data.append(char(0x01)); // payload length
data.append('c'); // payload
const QByteArray warningMsg = "Partial chunk not empty, but TNF not 0x06 as expected";
QTest::newRow("Incorrect TNF in chunk") << data << warningMsg;
}
{
QByteArray data;
data.append(char(0xB1)); // MB=1, ME=0, CF=1, SR=1, IL=0, TNF=1 (NFC-RTD)
data.append(char(0x01)); // type length
data.append(char(0x01)); // payload length
data.append('U'); // type
data.append('a'); // payload
data.append(char(0x36)); // MB=0, ME=0, CF=1, SR=1, IL=0, TNF=6 (Unchanged)
data.append(char(0x01)); // type length (incorrect)
data.append(char(0x01)); // payload length
data.append('U'); // type (incorrect)
data.append('b'); // payload
data.append(char(0x56)); // MB=0, ME=1, CF=0, SR=1, IL=0, TNF=6 (Unchanged)
data.append(char(0x00)); // type length
data.append(char(0x01)); // payload length
data.append('c'); // payload
const QByteArray warningMsg = "Invalid chunked data, TYPE_LENGTH != 0";
QTest::newRow("Incorrect TYPE_LENGTH in chunk") << data << warningMsg;
}
{
QByteArray data;
data.append(char(0xB1)); // MB=1, ME=0, CF=1, SR=1, IL=0, TNF=1 (NFC-RTD)
data.append(char(0x01)); // type length
data.append(char(0x01)); // payload length
data.append('U'); // type
data.append('a'); // payload
data.append(char(0x3E)); // MB=0, ME=0, CF=1, SR=1, IL=1 (incorrect), TNF=6 (Unchanged)
data.append(char(0x00)); // type length
data.append(char(0x01)); // payload length
data.append(char(0x01)); // id length (incorrect)
data.append('i'); // id (incorrect)
data.append('b'); // payload
data.append(char(0x56)); // MB=0, ME=1, CF=0, SR=1, IL=0, TNF=6 (Unchanged)
data.append(char(0x00)); // type length
data.append(char(0x01)); // payload length
data.append('c'); // payload
const QByteArray warningMsg = "Invalid chunked data, IL != 0";
QTest::newRow("Incorrect IL in chunk") << data << warningMsg;
}
{
QByteArray data;
data.append(char(0xC8)); // MB=1, ME=1, CF=0, SR=0, IL=1, TNF=0
data.append(char(0)); // type legnth
data.append(char(0)); // payload length (incorrect, 4 bytes expected)
const QByteArray warningMsg = "Unexpected end of message";
QTest::newRow("Invalid header length") << data << warningMsg;
}
{
QByteArray data;
data.append(char(0xC1)); // MB=1, ME=1, CF=0, SR=0, IL=0, TNF=1
data.append(char(0x01)); // type legnth
data.append(char(0xFF)); // payload length 3
data.append(char(0xFF)); // payload length 2
data.append(char(0xFF)); // payload length 1
data.append(char(0xFF)); // payload length 0
data.append('U'); // type
data.append('a'); // payload
// In case of 32 bit the code path will be different from 64 bit, so
// the warning message is also different.
const QByteArray warningMsg = (sizeof(qsizetype) <= sizeof(quint32))
? "Payload can't fit into QByteArray"
: "Unexpected end of message";
QTest::newRow("Max payload length") << data << warningMsg;
}
{
// QByteArray::fromHex("91010154411101015441560000");
QByteArray data;
data.append(char(0x91)); // MB=1, ME=0, CF=0, SR=1, IL=0, TNF=1
data.append(char(0x01)); // type length
data.append(char(0x01)); // payload length
data.append('T'); // type
data.append('A'); // payload
data.append(char(0x11)); // MB=0, ME=0, CF=0, SR=1, IL=0, TNF=1
data.append(char(0x01)); // type length
data.append(char(0x01)); // payload length
data.append('T'); // type
data.append('A'); // payload
data.append(char(0x56)); // MB=0, ME=1, CF=0, SR=1, IL=0, TNF=6 (Unchanged)
data.append(char(0x00)); // type length
data.append(char(0x00)); // payload length
const QByteArray warningMsg = "Unexpected TNF=0x06 when chunking was not started";
QTest::newRow("Unexpected TNF == Unchanged") << data << warningMsg;
}
}
void tst_QNdefMessage::parseComplexMessage()
{
const QByteArray reference("1234567890");
QNdefMessage message;
QNdefRecord first;
QVERIFY(first.isEmpty());
first.setTypeNameFormat(QNdefRecord::Uri);
QVERIFY(first.isEmpty());
first.setPayload(reference);
QCOMPARE(first.payload(), reference);
QVERIFY(!first.isEmpty());
QCOMPARE(first.typeNameFormat(), QNdefRecord::Uri);
message.append(first);
QNdefRecord second;
QCOMPARE(second.payload(), QByteArray());
QVERIFY(second.isEmpty());
QCOMPARE(second.typeNameFormat(), QNdefRecord::Empty);
message.append(second);
QByteArray result = message.toByteArray();
QNdefMessage messageCopy = QNdefMessage::fromByteArray(result);
QCOMPARE(messageCopy.size(), 2);
first = messageCopy.at(0);
second = messageCopy.at(1);
QCOMPARE(first.payload(), reference);
QVERIFY(!first.isEmpty());
QCOMPARE(first.typeNameFormat(), QNdefRecord::Uri);
QCOMPARE(second.payload(), QByteArray());
QVERIFY(second.isEmpty());
QCOMPARE(second.typeNameFormat(), QNdefRecord::Empty);
}
QTEST_MAIN(tst_QNdefMessage)
#include "tst_qndefmessage.moc"