// Reading and writing to a process is not supported on Qt/CE
void tst_QProcess::echoTest_performance()
{
    QProcess process;
    process.start("testProcessLoopback/testProcessLoopback");

    QByteArray array;
    array.resize(1024 * 1024);
    for (int j = 0; j < array.size(); ++j)
        array[j] = 'a' + (j % 20);

    QVERIFY(process.waitForStarted());

    QTime stopWatch;
    stopWatch.start();

    qint64 totalBytes = 0;
    QByteArray dump;
    QSignalSpy readyReadSpy(&process, SIGNAL(readyRead()));
    QVERIFY(readyReadSpy.isValid());
    while (stopWatch.elapsed() < 2000) {
        process.write(array);
        while (process.bytesToWrite() > 0) {
            int readCount = readyReadSpy.count();
            QVERIFY(process.waitForBytesWritten(5000));
            if (readyReadSpy.count() == readCount)
                QVERIFY(process.waitForReadyRead(5000));
        }

        while (process.bytesAvailable() < array.size())
            QVERIFY2(process.waitForReadyRead(5000), qPrintable(process.errorString()));
        dump = process.readAll();
        totalBytes += dump.size();
    }

    qDebug() << "Elapsed time:" << stopWatch.elapsed() << "ms;"
             << "transfer rate:" << totalBytes / (1048.576) / stopWatch.elapsed()
             << "MB/s";

    for (int j = 0; j < array.size(); ++j)
        QCOMPARE(char(dump.at(j)), char('a' + (j % 20)));

    process.closeWriteChannel();
    QVERIFY(process.waitForFinished());
}
/*!
 Description: LLCP Server API test & Socket readDatagram API test
 TestScenario:
     1) Read two datagrams from llcp client device
     2) Covered API: readDatagram(), serviceUri(), servicePort(), isListening(), serverError()
 */
void tst_QLlcpServer::api_coverage()
{
    QString uri = TestUri;
    QLlcpServer server;
    QSignalSpy connectionSpy(&server, SIGNAL(newConnection()));
    bool ret = server.listen(uri);
    QVERIFY(ret);

    QString message("api_coverage test");

    QNfcTestUtil::ShowAutoMsg(message, &connectionSpy, 1);
    QTRY_VERIFY(!connectionSpy.isEmpty());

    bool hasPending = server.hasPendingConnections();
    QVERIFY(hasPending);
    QLlcpSocket *socket = server.nextPendingConnection();
    QVERIFY(socket != NULL);
    QSignalSpy readyReadSpy(socket, SIGNAL(readyRead()));
    //Get data from client
    QTRY_VERIFY(!readyReadSpy.isEmpty());

    qint64 size = socket->bytesAvailable();
    QTRY_VERIFY(size > 0);
    QByteArray datagram;
    datagram.resize(size);
    qint64 readSize = socket->readDatagram(datagram.data(), datagram.size());
    QVERIFY(readSize == size);

    qDebug()<<"Server Uri = " << server.serviceUri();
    QCOMPARE(uri,server.serviceUri());

    quint8 unsupportedPort = 0;
    QCOMPARE(unsupportedPort,server.serverPort());

    QVERIFY(server.isListening() == true);
    QVERIFY(server.serverError() == QLlcpSocket::UnknownSocketError);
    server.close();
}
/*!
 Description: Add a llcp2 server which will always
 run( actually run twice ), then a client in a device connect,
 after the case finish, another device connect the
 server again.

 CounterPart: tst_qllcpsockettype2 echo:"0"
 run this case twice to test multiConnection()
*/
void tst_QLlcpServer::multiConnection()
{
    QString uri = TestUri;
    QString hint ="multiConnection test";

    QLlcpServer server;
    qDebug() << "Create QLlcpServer completed";
    qDebug() << "Start listening...";
    QSignalSpy connectionSpy(&server, SIGNAL(newConnection()));

    bool ret = server.listen(uri);
    QVERIFY(ret);
    qDebug() << "Listen() return ok";
    const int KLoopCount = 2;
    int loopCount = 0;
    while(loopCount < KLoopCount)
    {
        qDebug() << "#########Loop count = " << loopCount <<" #########";
        QNfcTestUtil::ShowAutoMsg(hint, &connectionSpy, 1);

        QTRY_VERIFY(!connectionSpy.isEmpty());
        qDebug() << "try to call nextPendingConnection()";
        QLlcpSocket *socket = server.nextPendingConnection();
        QVERIFY(socket != NULL);
        QSignalSpy readyReadSpy(socket, SIGNAL(readyRead()));
        QSignalSpy errorSpy(socket, SIGNAL(error(QLlcpSocket::SocketError)));

        //Get data from client
        QTRY_VERIFY(!readyReadSpy.isEmpty());

        qDebug() << "Bytes available = " << socket->bytesAvailable();
        quint16 blockSize = 0;
        QDataStream in(socket);
        in.setVersion(QDataStream::Qt_4_6);
        while (socket->bytesAvailable() < (int)sizeof(quint16)) {
            QSignalSpy readyRead(socket, SIGNAL(readyRead()));
            QTRY_VERIFY(!readyRead.isEmpty());
        }
        in >> blockSize;
        qDebug()<<"Read blockSize from client: " << blockSize;
        while (socket ->bytesAvailable() < blockSize) {
            QSignalSpy readyRead(socket, SIGNAL(readyRead()));
            QTRY_VERIFY(!readyRead.isEmpty());
        }
        QString echo;
        in >> echo;
        qDebug() << "Read data from client:" << echo;
        //Send data to client
        QSignalSpy bytesWrittenSpy(socket, SIGNAL(bytesWritten(qint64)));
        QByteArray block;
        QDataStream out(&block, QIODevice::WriteOnly);
        out.setVersion(QDataStream::Qt_4_6);
        out << (quint16)0;
        out << echo;
        qDebug()<<"Write echoed data back to client";
        out.device()->seek(0);
        out << (quint16)(block.size() - sizeof(quint16));
        qint64 val = socket->write(block);
        qDebug("Write() return value = %d", val);
        QVERIFY(val == 0);

        QTRY_VERIFY(!bytesWrittenSpy.isEmpty());
        qint64 written = countBytesWritten(bytesWrittenSpy);
        qDebug()<<"Server::bytesWritten signal return value = " << written;
        while (written < block.size())
        {
            QSignalSpy bytesWrittenSpy(socket, SIGNAL(bytesWritten(qint64)));
            QTRY_VERIFY(!bytesWrittenSpy.isEmpty());
            written += countBytesWritten(bytesWrittenSpy);
        }
        QVERIFY(written == block.size());
        //Now data has been sent,check the if existing error
        QVERIFY(errorSpy.isEmpty());

        connectionSpy.removeFirst();
        loopCount++;
    }
    QTest::qWait(1500);//give some time to client to finish
    server.close();
}
void tst_QLlcpSocket::tst_clientConnection()
{
    QFETCH(ClientConnectionShutdown, shutdown);
    QFETCH(bool, stream);

    QString service = QLatin1String("urn:nfc:sn:com.nokia.qtmobility.commandserver") +
                      (stream ? QLatin1String(".stream") : QLatin1String(".datagram"));

    /* Construction */
    QLlcpSocket *socket = new QLlcpSocket;

    QSignalSpy stateSpy(socket, SIGNAL(stateChanged(QLlcpSocket::SocketState)));

    QCOMPARE(socket->state(), QLlcpSocket::UnconnectedState);

    /* Connection */
    QSignalSpy connectedSpy(socket, SIGNAL(connected()));
    QSignalSpy errorSpy(socket, SIGNAL(error(QLlcpSocket::SocketError)));

    socket->connectToService(0, service);

    QCOMPARE(stateSpy.count(), 1);
    QCOMPARE(stateSpy.takeFirst().at(0).value<QLlcpSocket::SocketState>(),
             QLlcpSocket::ConnectingState);
    QCOMPARE(socket->state(), QLlcpSocket::ConnectingState);

    stateSpy.clear();

    QTRY_VERIFY_TIMEOUT(30000, !connectedSpy.isEmpty() || !errorSpy.isEmpty());

    if (errorSpy.count() != 0) {
        qDebug() << errorSpy.takeFirst().at(0).toInt();
        QSKIP("Connection error", SkipSingle);
    }

    QCOMPARE(connectedSpy.count(), 1);
    QCOMPARE(stateSpy.count(), 1);
    QCOMPARE(stateSpy.takeFirst().at(0).value<QLlcpSocket::SocketState>(),
             QLlcpSocket::ConnectedState);
    QCOMPARE(socket->state(), QLlcpSocket::ConnectedState);

    stateSpy.clear();

    QSignalSpy bytesWrittenSpy(socket, SIGNAL(bytesWritten(qint64)));
    QSignalSpy readyReadSpy(socket, SIGNAL(readyRead()));

    /* Verify connected to correct service */
    if (stream) {
        socket->write("URI\n");

        QCOMPARE(bytesWrittenSpy.count(), 1);
        QCOMPARE(bytesWrittenSpy.takeFirst().at(0).value<qint64>(), qint64(4));

        QTRY_VERIFY(!readyReadSpy.isEmpty() && socket->canReadLine());

        const QByteArray line = socket->readLine().trimmed();

        QCOMPARE(line, service.toLatin1());
    } else {
        socket->writeDatagram("URI");

        QCOMPARE(bytesWrittenSpy.count(), 1);
        QCOMPARE(bytesWrittenSpy.takeFirst().at(0).value<qint64>(), qint64(3));

        QTRY_VERIFY(!readyReadSpy.isEmpty() && socket->hasPendingDatagrams());

        QByteArray datagram;
        datagram.resize(socket->pendingDatagramSize());

        socket->readDatagram(datagram.data(), datagram.size());

        QCOMPARE(datagram, service.toLatin1());
    }

    bytesWrittenSpy.clear();
    readyReadSpy.clear();

    /* Read / Write */
    if (stream) {
        QByteArray data("ECHO Test data\n");
        socket->write(data);

        QCOMPARE(bytesWrittenSpy.count(), 1);
        QCOMPARE(bytesWrittenSpy.takeFirst().at(0).value<qint64>(), qint64(data.size()));

        QTRY_VERIFY(!readyReadSpy.isEmpty());

        const QByteArray line = socket->readLine().trimmed();

        QCOMPARE(line.constData(), "Test data");
    } else {
        socket->writeDatagram("ECHO Test data");

        QCOMPARE(bytesWrittenSpy.count(), 1);
        QCOMPARE(bytesWrittenSpy.takeFirst().at(0).value<qint64>(), qint64(14));

        QTRY_VERIFY(!readyReadSpy.isEmpty());

        QByteArray datagram;
        datagram.resize(socket->pendingDatagramSize());

        socket->readDatagram(datagram.data(), datagram.size());

        QCOMPARE(datagram.constData(), "Test data");
    }

    bytesWrittenSpy.clear();
    readyReadSpy.clear();

    QSignalSpy disconnectedSpy(socket, SIGNAL(disconnected()));
    errorSpy.clear();

    /* Shutdown */
    switch (shutdown) {
    case ServerDisconnect:
        if (stream)
            socket->write("DISCONNECT\n");
        else
            socket->writeDatagram("DISCONNECT");
        break;
    case ServerClose:
        if (stream)
            socket->write("CLOSE\n");
        else
            socket->writeDatagram("CLOSE");
        break;
    case ClientDisconnect:
        socket->disconnectFromService();
        break;
    case ClientClose:
        socket->close();
        break;
    }

    QTRY_VERIFY(!disconnectedSpy.isEmpty());

    QCOMPARE(disconnectedSpy.count(), 1);
    QCOMPARE(stateSpy.count(), 2);
    QCOMPARE(stateSpy.takeFirst().at(0).value<QLlcpSocket::SocketState>(),
             QLlcpSocket::ClosingState);
    QCOMPARE(stateSpy.takeFirst().at(0).value<QLlcpSocket::SocketState>(),
             QLlcpSocket::UnconnectedState);
    QVERIFY(!socket->isOpen());

    if (shutdown == ServerDisconnect || shutdown == ServerClose) {
        QTRY_VERIFY(!errorSpy.isEmpty());

        QCOMPARE(errorSpy.count(), 1);
        QCOMPARE(errorSpy.takeFirst().at(0).value<QLlcpSocket::SocketError>(),
                 QLlcpSocket::RemoteHostClosedError);
        QCOMPARE(socket->error(), QLlcpSocket::RemoteHostClosedError);
    }

    delete socket;
}