#include "plugins/protocols/modbus_rtu/framer/ModbusRtuFraming.h"

#include <QtTest/QtTest>

using softbus::message_bus::pipeline::protocol::modbusrtu::predictAduLength;
using softbus::message_bus::pipeline::protocol::modbusrtu::crc16;

namespace
{
void appendCrc(QByteArray& b)
{
    const auto c = crc16(reinterpret_cast<const std::uint8_t*>(b.constData()), static_cast<std::size_t>(b.size()));
    b.append(static_cast<char>(c & 0xFF));
    b.append(static_cast<char>((c >> 8) & 0xFF));
}
} // namespace

class ModbusRtuFramingPredictTest : public QObject
{
    Q_OBJECT
private slots:
    void readRequestWaitsUntilEightBytes();
    void readResponseNeedsWholeAndCrc();
};

void ModbusRtuFramingPredictTest::readRequestWaitsUntilEightBytes()
{
    QByteArray partial;
    partial.append('\x01');
    partial.append('\x03');
    partial.append('\x00');
    partial.append('\x00');
    partial.append('\x00');
    partial.append('\x0A');
    partial.append('\xC5'); // missing last crc byte
    auto pred = predictAduLength(reinterpret_cast<const std::uint8_t*>(partial.constData()),
                                 static_cast<std::size_t>(partial.size()), 256);
    QVERIFY(!pred.has_value());
}

void ModbusRtuFramingPredictTest::readResponseNeedsWholeAndCrc()
{
    QByteArray resp;
    resp.append('\x01');
    resp.append('\x03');
    resp.append('\x02');
    resp.append('\x12');
    resp.append('\x34');
    appendCrc(resp);
    auto pred = predictAduLength(reinterpret_cast<const std::uint8_t*>(resp.constData()),
                                 static_cast<std::size_t>(resp.size()), 256);
    QVERIFY(pred.has_value());
    QCOMPARE(static_cast<int>(*pred), resp.size());
}

QTEST_MAIN(ModbusRtuFramingPredictTest)
#include "modbus_rtu_framing_predict_test.moc"
