<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/QString>
#include <QtTest/QtTest>
#include <QtCore/QCoreApplication>

#include <qllcpsocket.h>
#include <qnearfieldmanager.h>
#include <qnearfieldtarget.h>
#include "qnfctestcommon.h"
#include "qnfctestutil.h"

QTM_USE_NAMESPACE

Q_DECLARE_METATYPE(QNearFieldTarget*)
Q_DECLARE_METATYPE(QLlcpSocket::Error)
Q_DECLARE_METATYPE(QLlcpSocket::State)

class tst_qllcpsocketlocal : public QObject
{
    Q_OBJECT

public:
    tst_qllcpsocketlocal();
private Q_SLOTS:

    // ALERT: Handshake required, do NOT change the sequence of handshaking testcases.
    void testCase0();  // Intial handshake - work with  tst_qllcpsocketremote testCase0
    void testCase1();   // handshake 1,2  - work with  tst_qllcpsocketremote testCase1
    void testCase2();   // handshake 3   - work with  tst_qllcpsocketremote testCase2
    void testCase3();
    void coverageTest1();

    void negTestCase1();
    void negTestCase2();
    //void negTestCase3();
    //void negTestCase4();

    void cleanupTest();

private:
     QNearFieldManager *m_nfcManager; //own
     QNearFieldTarget *m_target; // not own
     quint8 m_port;
     QLlcpSocket *m_socket;
};

tst_qllcpsocketlocal::tst_qllcpsocketlocal()
{
    qRegisterMetaType<QNearFieldTarget *>("QNearFieldTarget*");
    qRegisterMetaType<QNearFieldTarget *>("QLlcpSocket::Error");
    qRegisterMetaType<QNearFieldTarget *>("QLlcpSocket::State");
}

/*!
 Description: Init test case for NFC LLCP connection-less mode socket - local peer

 TestScenario:
     Touch a NFC device with LLCP connection-less service actived

 TestExpectedResults:
     Signal of target detected has been found.
*/
void tst_qllcpsocketlocal::testCase0()
{
    m_nfcManager = new QNearFieldManager;
    QSignalSpy targetDetectedSpy(m_nfcManager, SIGNAL(targetDetected(QNearFieldTarget*)));
    m_nfcManager->startTargetDetection(QNearFieldTarget::AnyTarget);

    QString message("Local Wait touch");
    QNfcTestUtil::ShowMessage(message);
    QTRY_VERIFY(!targetDetectedSpy.isEmpty());

    m_target = targetDetectedSpy.at(targetDetectedSpy.count() - 1).at(0).value<QNearFieldTarget *>();
    QVERIFY(m_target!=NULL);
    QVERIFY(m_target->accessMethods() & QNearFieldTarget::LlcpAccess);
    m_port = 35;

    m_socket = new QLlcpSocket;
}

/*!
 Description: Send the message and Receive the acknowledged identical message

 TestScenario:
           1. Local peer temps to read datagram without bind
           2. Local peer binds to the remote peer
           3. Local peer sends the "testcase1 string" message to the remote peer
           4. Local peer receives the above message sending from the remote peer

 TestExpectedResults:
           1. Local peer fails to read datagram without bind
           2. Local peer binds to local port successfully.
           3. The message has be sent to remote peer.
           4. The message has been received from remote peer.
*/
void tst_qllcpsocketlocal::testCase1()
{
    QString message("testcase1 string");
    //QLlcpSocket socket(this);

    // STEP 1.  readDatagram must be called before bind
    QByteArray tmpForReadArray;
    tmpForReadArray.resize(127);
    qint64 ret = m_socket->readDatagram(tmpForReadArray.data(), tmpForReadArray.size());
    QVERIFY(ret == -1);

    QCOMPARE(m_socket->state(), QLlcpSocket::UnconnectedState);
    QSignalSpy stateChangedSpy(m_socket, SIGNAL(stateChanged(QLlcpSocket::State)));

    // STEP 2:  bind the local port for current socket
    QSignalSpy readyReadSpy(m_socket, SIGNAL(readyRead()));
    bool retBool = m_socket->bind(m_port);
    QVERIFY(retBool);
    QVERIFY(!stateChangedSpy.isEmpty());
    QCOMPARE(m_socket->state(), QLlcpSocket::BoundState);

    QString messageBox("handshake 1");
    QNfcTestUtil::ShowMessage(messageBox);

    // STEP 3: Local peer sends the  message to the remote peer
    QSignalSpy errorSpy(m_socket, SIGNAL(error(QLlcpSocket::Error)));
    QSignalSpy bytesWrittenSpy(m_socket, SIGNAL(bytesWritten(qint64)));

    QByteArray tmpArray(message.toAscii());
    const char* data =  tmpArray.data();
    qint64 strSize = message.size();
    m_socket->writeDatagram(data,strSize,m_target, m_port);

    QTRY_VERIFY(bytesWrittenSpy.count() == 1);
    QList<QVariant> arguments = bytesWrittenSpy.takeFirst(); // take the first signal
    qint64 writtenSize  = arguments.at(0).value<qint64>();
    QCOMPARE(writtenSize, strSize);

    QString messageBox2("handshake 2");
    QNfcTestUtil::ShowMessage(messageBox2);

    // STEP 4: Receive data from remote peer
    QTRY_VERIFY(!readyReadSpy.isEmpty());
    QByteArray datagram;
    while (m_socket->hasPendingDatagrams())
    {
       datagram.resize(m_socket->pendingDatagramSize());
       quint8 remotePort = 0;
       qint64 readSize = m_socket->readDatagram(datagram.data(), datagram.size(),&m_target, &remotePort);
       QVERIFY(readSize != -1);
       QVERIFY(remotePort > 0);
    }

    // verify the echoed string is same as the original string
    QString receivedMessage = datagram.data();
    QVERIFY(message == receivedMessage);

    // make sure the no error signal emitted
    QVERIFY(errorSpy.isEmpty());
}

/*!
 Description: waitForBytesWritten test

 TestScenario:
               1. Local peer sends the "testcase2 string str1" message to the remote peer
               2. Local peer sends the "testcase2 string str2" message to the remote peer
               3. Local peer waits for the bytes written
               4. call waitForBytesWritten

 TestExpectedResults:
               1. Local peer write datagram successfully firstly
               2. Local peer write datagram successfully secondly
               3. call waitForBytesWritten successfully
               4. call waitForBytesWritten successfully
*/
/*
void tst_qllcpsocketlocal::testCase2()
{
    // STEP 1:
    QSignalSpy bytesWrittenSpy(m_socket, SIGNAL(bytesWritten(qint64)));
    QString message("testcase2 string str1");
    QByteArray tmpArray(message.toAscii());
    const char* data =  tmpArray.data();
    qint64 strSize = message.size();
    qint64 val = m_socket->writeDatagram(data,strSize,m_target, m_port);
    QVERIFY(val != -1);

    // STEP 2:
    QString message2("testcase2 string str2");
    QByteArray tmpArray2(message2.toAscii());
    const char* data2 =  tmpArray2.data();
    qint64 strSize2 = message2.size();
    qint64 val2 = m_socket->writeDatagram(data2,strSize2,m_target, m_port);
    QVERIFY(val2 != -1);

    // STEP 3:
    const int Timeout = 2 * 1000;
    bool ret = m_socket->waitForBytesWritten(Timeout);
    QVERIFY(ret == true);

     // STEP 4:
    ret = m_socket->waitForBytesWritten(Timeout);
    QVERIFY(ret == true);

    QString messageBox("handshake 3");
    QNfcTestUtil::ShowMessage(messageBox);

    QVERIFY(ret == true);
}
*/

void tst_qllcpsocketlocal::testCase2()
{
    QLlcpSocket *socket = new QLlcpSocket;
    quint8 localPort = 38;

    // STEP 1:
    QSignalSpy bytesWrittenSpy(socket, SIGNAL(bytesWritten(qint64)));
    QString message("testcase2 string str1");
    QByteArray tmpArray(message.toAscii());
    const char* data =  tmpArray.data();
    qint64 strSize = message.size();
    qint64 val = socket->writeDatagram(data,strSize,m_target, localPort);
    QVERIFY(val != -1);

    // STEP 2:
    QString message2("testcase2 string str2");
    QByteArray tmpArray2(message2.toAscii());
    const char* data2 =  tmpArray2.data();
    qint64 strSize2 = message2.size();
    qint64 val2 = socket->writeDatagram(data2,strSize2,m_target, localPort);
    QVERIFY(val2 != -1);

    // STEP 3:
    const int Timeout = 2 * 1000;
    bool ret = socket->waitForBytesWritten(Timeout);
    QVERIFY(ret == true);

     // STEP 4:
    ret = socket->waitForBytesWritten(Timeout);
    QVERIFY(ret == true);

    QString messageBox("handshake 3");
    QNfcTestUtil::ShowMessage(messageBox);

    // STEP 5:
    const int Timeout = 1 * 1000;
    m_socket->waitForBytesWritten(Timeout);

    delete socket;
    QVERIFY(ret == true);
}

/*!
 Description: coverage testcase - targeted for sender doCancel
*/
void tst_qllcpsocketlocal::testCase3()
{
    QLlcpSocket *localSocket= new QLlcpSocket;
    // STEP 1:
    QString message("string1");
    QByteArray tmpArray(message.toAscii());
    const char* data =  tmpArray.data();
    qint64 strSize = message.size();
    localSocket->writeDatagram(data,strSize,m_target, m_port);
    delete localSocket;
}

/*!
 Description: coverage testcase - invalid usage of connection-oriented API
*/
void tst_qllcpsocketlocal::coverageTest1()
{
    QSignalSpy errorSpy(m_socket, SIGNAL(error(QLlcpSocket::Error)));
    m_socket->connectToService(m_target,"uri");
    QTRY_VERIFY(errorSpy.count() == 1);
    QVERIFY(m_socket->error() == QLlcpSocket::UnknownSocketError);

    m_socket->disconnectFromService();
    QTRY_VERIFY(errorSpy.count() == 2);

    QVERIFY(m_socket->waitForConnected() == false);
    QVERIFY(m_socket->waitForDisconnected() == false);

    QString message = "Oops, must follow a port parameter";
    QByteArray tmpArray(message.toAscii());
    const char* data =  tmpArray.data();
    qint64 strSize = message.size();
    qint64 ret = m_socket->writeDatagram(data,strSize);
    QVERIFY(ret == -1);
}

/*!
 Description: writeDatagram negative testcase I - invalid port num & wait* functions
*/
void tst_qllcpsocketlocal::negTestCase1()
{
    QLlcpSocket localSocket;
    QString message = "Oops, Invalid port num for writeDatagram";
    QByteArray tmpArray(message.toAscii());
    const char* data =  tmpArray.data();
    qint64 strSize = message.size();
    qint8 invalidPort = -1;
    qint64 ret = localSocket.writeDatagram(data,strSize,m_target, invalidPort);
    QVERIFY(ret == -1);

    const int Timeout = 1 * 500;
    bool retBool = localSocket.waitForBytesWritten(Timeout);
    QVERIFY(retBool == false);

    //Cover QLLCPUnConnected::WaitForReadyRead
    retBool = localSocket.waitForReadyRead(Timeout);
    QVERIFY(retBool == false);

    //Cover QLLCPBind::WaitForReadyRead()
    retBool = localSocket.waitForReadyRead(Timeout);
    QVERIFY(retBool == false);
}

/*!
 Description: bind negative test - double bind
*/
void tst_qllcpsocketlocal::negTestCase2()
{
    // bind again will cause failure
    bool ret2 = m_socket->bind(m_port);
    QVERIFY(ret2 == false);

    delete m_socket;
    m_socket = NULL;
}

/*!
 Description: bind negative test - invalid port num
*/
/*
void tst_qllcpsocketlocal::negTestCase3()
{
    QLlcpSocket localSocket;
    bool ret = localSocket.bind(65);
    QVERIFY(ret == false);
}
*/

/*!
 Description: bind negative test - invalid port num II
*/
/*
void tst_qllcpsocketlocal::negTestCase4()
{
    QLlcpSocket localSocket;
    int reservedPort = 15;
    bool ret = localSocket.bind(reservedPort);
    QVERIFY(ret == false);
}
*/

void tst_qllcpsocketlocal::cleanupTest()
{
    delete m_nfcManager;
    delete m_socket;
}

QTEST_MAIN(tst_qllcpsocketlocal);

#include "tst_qllcpsocketlocal.moc"
<commit_msg>fix the typo to pass build<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/QString>
#include <QtTest/QtTest>
#include <QtCore/QCoreApplication>

#include <qllcpsocket.h>
#include <qnearfieldmanager.h>
#include <qnearfieldtarget.h>
#include "qnfctestcommon.h"
#include "qnfctestutil.h"

QTM_USE_NAMESPACE

Q_DECLARE_METATYPE(QNearFieldTarget*)
Q_DECLARE_METATYPE(QLlcpSocket::Error)
Q_DECLARE_METATYPE(QLlcpSocket::State)

class tst_qllcpsocketlocal : public QObject
{
    Q_OBJECT

public:
    tst_qllcpsocketlocal();
private Q_SLOTS:

    // ALERT: Handshake required, do NOT change the sequence of handshaking testcases.
    void testCase0();  // Intial handshake - work with  tst_qllcpsocketremote testCase0
    void testCase1();   // handshake 1,2  - work with  tst_qllcpsocketremote testCase1
    void testCase2();   // handshake 3   - work with  tst_qllcpsocketremote testCase2
    void testCase3();
    void coverageTest1();

    void negTestCase1();
    void negTestCase2();
    //void negTestCase3();
    //void negTestCase4();

    void cleanupTest();

private:
     QNearFieldManager *m_nfcManager; //own
     QNearFieldTarget *m_target; // not own
     quint8 m_port;
     QLlcpSocket *m_socket;
};

tst_qllcpsocketlocal::tst_qllcpsocketlocal()
{
    qRegisterMetaType<QNearFieldTarget *>("QNearFieldTarget*");
    qRegisterMetaType<QNearFieldTarget *>("QLlcpSocket::Error");
    qRegisterMetaType<QNearFieldTarget *>("QLlcpSocket::State");
}

/*!
 Description: Init test case for NFC LLCP connection-less mode socket - local peer

 TestScenario:
     Touch a NFC device with LLCP connection-less service actived

 TestExpectedResults:
     Signal of target detected has been found.
*/
void tst_qllcpsocketlocal::testCase0()
{
    m_nfcManager = new QNearFieldManager;
    QSignalSpy targetDetectedSpy(m_nfcManager, SIGNAL(targetDetected(QNearFieldTarget*)));
    m_nfcManager->startTargetDetection(QNearFieldTarget::AnyTarget);

    QString message("Local Wait touch");
    QNfcTestUtil::ShowMessage(message);
    QTRY_VERIFY(!targetDetectedSpy.isEmpty());

    m_target = targetDetectedSpy.at(targetDetectedSpy.count() - 1).at(0).value<QNearFieldTarget *>();
    QVERIFY(m_target!=NULL);
    QVERIFY(m_target->accessMethods() & QNearFieldTarget::LlcpAccess);
    m_port = 35;

    m_socket = new QLlcpSocket;
}

/*!
 Description: Send the message and Receive the acknowledged identical message

 TestScenario:
           1. Local peer temps to read datagram without bind
           2. Local peer binds to the remote peer
           3. Local peer sends the "testcase1 string" message to the remote peer
           4. Local peer receives the above message sending from the remote peer

 TestExpectedResults:
           1. Local peer fails to read datagram without bind
           2. Local peer binds to local port successfully.
           3. The message has be sent to remote peer.
           4. The message has been received from remote peer.
*/
void tst_qllcpsocketlocal::testCase1()
{
    QString message("testcase1 string");
    //QLlcpSocket socket(this);

    // STEP 1.  readDatagram must be called before bind
    QByteArray tmpForReadArray;
    tmpForReadArray.resize(127);
    qint64 ret = m_socket->readDatagram(tmpForReadArray.data(), tmpForReadArray.size());
    QVERIFY(ret == -1);

    QCOMPARE(m_socket->state(), QLlcpSocket::UnconnectedState);
    QSignalSpy stateChangedSpy(m_socket, SIGNAL(stateChanged(QLlcpSocket::State)));

    // STEP 2:  bind the local port for current socket
    QSignalSpy readyReadSpy(m_socket, SIGNAL(readyRead()));
    bool retBool = m_socket->bind(m_port);
    QVERIFY(retBool);
    QVERIFY(!stateChangedSpy.isEmpty());
    QCOMPARE(m_socket->state(), QLlcpSocket::BoundState);

    QString messageBox("handshake 1");
    QNfcTestUtil::ShowMessage(messageBox);

    // STEP 3: Local peer sends the  message to the remote peer
    QSignalSpy errorSpy(m_socket, SIGNAL(error(QLlcpSocket::Error)));
    QSignalSpy bytesWrittenSpy(m_socket, SIGNAL(bytesWritten(qint64)));

    QByteArray tmpArray(message.toAscii());
    const char* data =  tmpArray.data();
    qint64 strSize = message.size();
    m_socket->writeDatagram(data,strSize,m_target, m_port);

    QTRY_VERIFY(bytesWrittenSpy.count() == 1);
    QList<QVariant> arguments = bytesWrittenSpy.takeFirst(); // take the first signal
    qint64 writtenSize  = arguments.at(0).value<qint64>();
    QCOMPARE(writtenSize, strSize);

    QString messageBox2("handshake 2");
    QNfcTestUtil::ShowMessage(messageBox2);

    // STEP 4: Receive data from remote peer
    QTRY_VERIFY(!readyReadSpy.isEmpty());
    QByteArray datagram;
    while (m_socket->hasPendingDatagrams())
    {
       datagram.resize(m_socket->pendingDatagramSize());
       quint8 remotePort = 0;
       qint64 readSize = m_socket->readDatagram(datagram.data(), datagram.size(),&m_target, &remotePort);
       QVERIFY(readSize != -1);
       QVERIFY(remotePort > 0);
    }

    // verify the echoed string is same as the original string
    QString receivedMessage = datagram.data();
    QVERIFY(message == receivedMessage);

    // make sure the no error signal emitted
    QVERIFY(errorSpy.isEmpty());
}

/*!
 Description: waitForBytesWritten test

 TestScenario:
               1. Local peer sends the "testcase2 string str1" message to the remote peer
               2. Local peer sends the "testcase2 string str2" message to the remote peer
               3. Local peer waits for the bytes written
               4. call waitForBytesWritten

 TestExpectedResults:
               1. Local peer write datagram successfully firstly
               2. Local peer write datagram successfully secondly
               3. call waitForBytesWritten successfully
               4. call waitForBytesWritten successfully
*/
/*
void tst_qllcpsocketlocal::testCase2()
{
    // STEP 1:
    QSignalSpy bytesWrittenSpy(m_socket, SIGNAL(bytesWritten(qint64)));
    QString message("testcase2 string str1");
    QByteArray tmpArray(message.toAscii());
    const char* data =  tmpArray.data();
    qint64 strSize = message.size();
    qint64 val = m_socket->writeDatagram(data,strSize,m_target, m_port);
    QVERIFY(val != -1);

    // STEP 2:
    QString message2("testcase2 string str2");
    QByteArray tmpArray2(message2.toAscii());
    const char* data2 =  tmpArray2.data();
    qint64 strSize2 = message2.size();
    qint64 val2 = m_socket->writeDatagram(data2,strSize2,m_target, m_port);
    QVERIFY(val2 != -1);

    // STEP 3:
    const int Timeout = 2 * 1000;
    bool ret = m_socket->waitForBytesWritten(Timeout);
    QVERIFY(ret == true);

     // STEP 4:
    ret = m_socket->waitForBytesWritten(Timeout);
    QVERIFY(ret == true);

    QString messageBox("handshake 3");
    QNfcTestUtil::ShowMessage(messageBox);

    QVERIFY(ret == true);
}
*/

void tst_qllcpsocketlocal::testCase2()
{
    QLlcpSocket *socket = new QLlcpSocket;
    quint8 localPort = 38;

    // STEP 1:
    QSignalSpy bytesWrittenSpy(socket, SIGNAL(bytesWritten(qint64)));
    QString message("testcase2 string str1");
    QByteArray tmpArray(message.toAscii());
    const char* data =  tmpArray.data();
    qint64 strSize = message.size();
    qint64 val = socket->writeDatagram(data,strSize,m_target, localPort);
    QVERIFY(val != -1);

    // STEP 2:
    QString message2("testcase2 string str2");
    QByteArray tmpArray2(message2.toAscii());
    const char* data2 =  tmpArray2.data();
    qint64 strSize2 = message2.size();
    qint64 val2 = socket->writeDatagram(data2,strSize2,m_target, localPort);
    QVERIFY(val2 != -1);

    // STEP 3:
    const int Timeout = 2 * 1000;
    bool ret = socket->waitForBytesWritten(Timeout);
    QVERIFY(ret == true);

     // STEP 4:
    ret = socket->waitForBytesWritten(Timeout);
    QVERIFY(ret == true);

    QString messageBox("handshake 3");
    QNfcTestUtil::ShowMessage(messageBox);

    // STEP 5:
    const int Timeout1 = 1 * 1000;
    m_socket->waitForBytesWritten(Timeout1);

    delete socket;
    QVERIFY(ret == true);
}

/*!
 Description: coverage testcase - targeted for sender doCancel
*/
void tst_qllcpsocketlocal::testCase3()
{
    QLlcpSocket *localSocket= new QLlcpSocket;
    // STEP 1:
    QString message("string1");
    QByteArray tmpArray(message.toAscii());
    const char* data =  tmpArray.data();
    qint64 strSize = message.size();
    localSocket->writeDatagram(data,strSize,m_target, m_port);
    delete localSocket;
}

/*!
 Description: coverage testcase - invalid usage of connection-oriented API
*/
void tst_qllcpsocketlocal::coverageTest1()
{
    QSignalSpy errorSpy(m_socket, SIGNAL(error(QLlcpSocket::Error)));
    m_socket->connectToService(m_target,"uri");
    QTRY_VERIFY(errorSpy.count() == 1);
    QVERIFY(m_socket->error() == QLlcpSocket::UnknownSocketError);

    m_socket->disconnectFromService();
    QTRY_VERIFY(errorSpy.count() == 2);

    QVERIFY(m_socket->waitForConnected() == false);
    QVERIFY(m_socket->waitForDisconnected() == false);

    QString message = "Oops, must follow a port parameter";
    QByteArray tmpArray(message.toAscii());
    const char* data =  tmpArray.data();
    qint64 strSize = message.size();
    qint64 ret = m_socket->writeDatagram(data,strSize);
    QVERIFY(ret == -1);
}

/*!
 Description: writeDatagram negative testcase I - invalid port num & wait* functions
*/
void tst_qllcpsocketlocal::negTestCase1()
{
    QLlcpSocket localSocket;
    QString message = "Oops, Invalid port num for writeDatagram";
    QByteArray tmpArray(message.toAscii());
    const char* data =  tmpArray.data();
    qint64 strSize = message.size();
    qint8 invalidPort = -1;
    qint64 ret = localSocket.writeDatagram(data,strSize,m_target, invalidPort);
    QVERIFY(ret == -1);

    const int Timeout = 1 * 500;
    bool retBool = localSocket.waitForBytesWritten(Timeout);
    QVERIFY(retBool == false);

    //Cover QLLCPUnConnected::WaitForReadyRead
    retBool = localSocket.waitForReadyRead(Timeout);
    QVERIFY(retBool == false);

    //Cover QLLCPBind::WaitForReadyRead()
    retBool = localSocket.waitForReadyRead(Timeout);
    QVERIFY(retBool == false);
}

/*!
 Description: bind negative test - double bind
*/
void tst_qllcpsocketlocal::negTestCase2()
{
    // bind again will cause failure
    bool ret2 = m_socket->bind(m_port);
    QVERIFY(ret2 == false);

    delete m_socket;
    m_socket = NULL;
}

/*!
 Description: bind negative test - invalid port num
*/
/*
void tst_qllcpsocketlocal::negTestCase3()
{
    QLlcpSocket localSocket;
    bool ret = localSocket.bind(65);
    QVERIFY(ret == false);
}
*/

/*!
 Description: bind negative test - invalid port num II
*/
/*
void tst_qllcpsocketlocal::negTestCase4()
{
    QLlcpSocket localSocket;
    int reservedPort = 15;
    bool ret = localSocket.bind(reservedPort);
    QVERIFY(ret == false);
}
*/

void tst_qllcpsocketlocal::cleanupTest()
{
    delete m_nfcManager;
    delete m_socket;
}

QTEST_MAIN(tst_qllcpsocketlocal);

#include "tst_qllcpsocketlocal.moc"
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef __MESOS_SLAVE_ISOLATOR_HPP__
#define __MESOS_SLAVE_ISOLATOR_HPP__

#include <list>
#include <string>

#include <mesos/resources.hpp>

#include <mesos/slave/containerizer.hpp>

#include <process/dispatch.hpp>
#include <process/future.hpp>
#include <process/owned.hpp>
#include <process/process.hpp>

#include <stout/hashset.hpp>
#include <stout/option.hpp>
#include <stout/try.hpp>

namespace mesos {
namespace slave {

class Isolator
{
public:
  virtual ~Isolator() {}

  // Returns true if this isolator supports nested containers. This
  // method is designed to allow isolators to opt-in to support nested
  // containers.
  virtual bool supportsNesting()
  {
    return false;
  }

  // Recover containers from the run states and the orphan containers
  // (known to the launcher but not known to the slave) detected by
  // the launcher.
  virtual process::Future<Nothing> recover(
      const std::list<ContainerState>& states,
      const hashset<ContainerID>& orphans)
  {
    return Nothing();
  }

  // Prepare for isolation of the executor. Any steps that require
  // execution in the containerized context (e.g. inside a network
  // namespace) can be returned in the optional CommandInfo and they
  // will be run by the Launcher.
  // TODO(idownes): Any URIs or Environment in the CommandInfo will be
  // ignored; only the command value is used.
  virtual process::Future<Option<ContainerLaunchInfo>> prepare(
      const ContainerID& containerId,
      const ContainerConfig& containerConfig)
  {
    return None();
  }

  // Isolate the executor.
  virtual process::Future<Nothing> isolate(
      const ContainerID& containerId,
      pid_t pid)
  {
    return Nothing();
  }

  // Watch the containerized executor and report if any resource
  // constraint impacts the container, e.g., the kernel killing some
  // processes.
  virtual process::Future<ContainerLimitation> watch(
      const ContainerID& containerId)
  {
    return process::Future<ContainerLimitation>();
  }

  // Update the resources allocated to the container.
  virtual process::Future<Nothing> update(
      const ContainerID& containerId,
      const Resources& resources)
  {
    return Nothing();
  }

  // Gather resource usage statistics for the container.
  virtual process::Future<ResourceStatistics> usage(
      const ContainerID& containerId)
  {
    return ResourceStatistics();
  }

  // Get the run-time status of isolator specific properties
  // associated with the container.
  virtual process::Future<ContainerStatus> status(
      const ContainerID& containerId)
  {
    return ContainerStatus();
  };

  // Clean up a terminated container. This is called after the
  // executor and all processes in the container have terminated.
  // It's likely that isolator `cleanup` is called for an unknown
  // container (see MESOS-6059). Therefore, the isolator should ignore
  // the cleanup is the container is unknown to it. In any case, the
  // `cleanup` won't be called multiple times for a container. Also,
  // if `prepare` is called, the cleanup is guaranteed to be called
  // after `prepare` finishes (or fails).
  virtual process::Future<Nothing> cleanup(
      const ContainerID& containerId)
  {
    return Nothing();
  }
};

} // namespace slave {
} // namespace mesos {

#endif // __MESOS_SLAVE_ISOLATOR_HPP__
<commit_msg>Removed extra ';' from "isolator.hpp".<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef __MESOS_SLAVE_ISOLATOR_HPP__
#define __MESOS_SLAVE_ISOLATOR_HPP__

#include <list>
#include <string>

#include <mesos/resources.hpp>

#include <mesos/slave/containerizer.hpp>

#include <process/dispatch.hpp>
#include <process/future.hpp>
#include <process/owned.hpp>
#include <process/process.hpp>

#include <stout/hashset.hpp>
#include <stout/option.hpp>
#include <stout/try.hpp>

namespace mesos {
namespace slave {

class Isolator
{
public:
  virtual ~Isolator() {}

  // Returns true if this isolator supports nested containers. This
  // method is designed to allow isolators to opt-in to support nested
  // containers.
  virtual bool supportsNesting()
  {
    return false;
  }

  // Recover containers from the run states and the orphan containers
  // (known to the launcher but not known to the slave) detected by
  // the launcher.
  virtual process::Future<Nothing> recover(
      const std::list<ContainerState>& states,
      const hashset<ContainerID>& orphans)
  {
    return Nothing();
  }

  // Prepare for isolation of the executor. Any steps that require
  // execution in the containerized context (e.g. inside a network
  // namespace) can be returned in the optional CommandInfo and they
  // will be run by the Launcher.
  // TODO(idownes): Any URIs or Environment in the CommandInfo will be
  // ignored; only the command value is used.
  virtual process::Future<Option<ContainerLaunchInfo>> prepare(
      const ContainerID& containerId,
      const ContainerConfig& containerConfig)
  {
    return None();
  }

  // Isolate the executor.
  virtual process::Future<Nothing> isolate(
      const ContainerID& containerId,
      pid_t pid)
  {
    return Nothing();
  }

  // Watch the containerized executor and report if any resource
  // constraint impacts the container, e.g., the kernel killing some
  // processes.
  virtual process::Future<ContainerLimitation> watch(
      const ContainerID& containerId)
  {
    return process::Future<ContainerLimitation>();
  }

  // Update the resources allocated to the container.
  virtual process::Future<Nothing> update(
      const ContainerID& containerId,
      const Resources& resources)
  {
    return Nothing();
  }

  // Gather resource usage statistics for the container.
  virtual process::Future<ResourceStatistics> usage(
      const ContainerID& containerId)
  {
    return ResourceStatistics();
  }

  // Get the run-time status of isolator specific properties
  // associated with the container.
  virtual process::Future<ContainerStatus> status(
      const ContainerID& containerId)
  {
    return ContainerStatus();
  }

  // Clean up a terminated container. This is called after the
  // executor and all processes in the container have terminated.
  // It's likely that isolator `cleanup` is called for an unknown
  // container (see MESOS-6059). Therefore, the isolator should ignore
  // the cleanup is the container is unknown to it. In any case, the
  // `cleanup` won't be called multiple times for a container. Also,
  // if `prepare` is called, the cleanup is guaranteed to be called
  // after `prepare` finishes (or fails).
  virtual process::Future<Nothing> cleanup(
      const ContainerID& containerId)
  {
    return Nothing();
  }
};

} // namespace slave {
} // namespace mesos {

#endif // __MESOS_SLAVE_ISOLATOR_HPP__
<|endoftext|>


<commit_before>// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Tool to upload an exe/dll and its associated symbols to an HTTP server.
// The PDB file is located automatically, using the path embedded in the
// executable.  The upload is sent as a multipart/form-data POST request,
// with the following parameters:
//  code_file: the basename of the module, e.g. "app.exe"
//  debug_file: the basename of the debugging file, e.g. "app.pdb"
//  debug_identifier: the debug file's identifier, usually consisting of
//                    the guid and age embedded in the pdb, e.g.
//                    "11111111BBBB3333DDDD555555555555F"
//  product: the HTTP-friendly product name, e.g. "MyApp"
//  version: the file version of the module, e.g. "1.2.3.4"
//  os: the operating system that the module was built for, always
//      "windows" in this implementation.
//  cpu: the CPU that the module was built for, typically "x86".
//  symbol_file: the contents of the breakpad-format symbol file

#include <windows.h>
#include <dbghelp.h>
#include <wininet.h>

#include <cstdio>
#include <map>
#include <string>
#include <vector>

#include "common/windows/string_utils-inl.h"

#include "common/windows/http_upload.h"
#include "common/windows/pdb_source_line_writer.h"

using std::string;
using std::wstring;
using std::vector;
using std::map;
using google_breakpad::HTTPUpload;
using google_breakpad::PDBModuleInfo;
using google_breakpad::PDBSourceLineWriter;
using google_breakpad::WindowsStringUtils;

// Extracts the file version information for the given filename,
// as a string, for example, "1.2.3.4".  Returns true on success.
static bool GetFileVersionString(const wchar_t *filename, wstring *version) {
  DWORD handle;
  DWORD version_size = GetFileVersionInfoSize(filename, &handle);
  if (version_size < sizeof(VS_FIXEDFILEINFO)) {
    return false;
  }

  vector<char> version_info(version_size);
  if (!GetFileVersionInfo(filename, handle, version_size, &version_info[0])) {
    return false;
  }

  void *file_info_buffer = NULL;
  unsigned int file_info_length;
  if (!VerQueryValue(&version_info[0], L"\\",
                     &file_info_buffer, &file_info_length)) {
    return false;
  }

  // The maximum value of each version component is 65535 (0xffff),
  // so the max length is 24, including the terminating null.
  wchar_t ver_string[24];
  VS_FIXEDFILEINFO *file_info =
    reinterpret_cast<VS_FIXEDFILEINFO*>(file_info_buffer);
  swprintf(ver_string, sizeof(ver_string) / sizeof(ver_string[0]),
           L"%d.%d.%d.%d",
           file_info->dwFileVersionMS >> 16,
           file_info->dwFileVersionMS & 0xffff,
           file_info->dwFileVersionLS >> 16,
           file_info->dwFileVersionLS & 0xffff);

  // remove when VC++7.1 is no longer supported
  ver_string[sizeof(ver_string) / sizeof(ver_string[0]) - 1] = L'\0';

  *version = ver_string;
  return true;
}

// Creates a new temporary file and writes the symbol data from the given
// exe/dll file to it.  Returns the path to the temp file in temp_file_path
// and information about the pdb in pdb_info.
static bool DumpSymbolsToTempFile(const wchar_t *file,
                                  wstring *temp_file_path,
                                  PDBModuleInfo *pdb_info) {
  google_breakpad::PDBSourceLineWriter writer;
  // Use EXE_FILE to get information out of the exe/dll in addition to the
  // pdb.  The name and version number of the exe/dll are of value, and
  // there's no way to locate an exe/dll given a pdb.
  if (!writer.Open(file, PDBSourceLineWriter::EXE_FILE)) {
    return false;
  }

  wchar_t temp_path[_MAX_PATH];
  if (GetTempPath(_MAX_PATH, temp_path) == 0) {
    return false;
  }

  wchar_t temp_filename[_MAX_PATH];
  if (GetTempFileName(temp_path, L"sym", 0, temp_filename) == 0) {
    return false;
  }

  FILE *temp_file = NULL;
#if _MSC_VER >= 1400  // MSVC 2005/8
  if (_wfopen_s(&temp_file, temp_filename, L"w") != 0)
#else  // _MSC_VER >= 1400
  // _wfopen_s was introduced in MSVC8.  Use _wfopen for earlier environments.
  // Don't use it with MSVC8 and later, because it's deprecated.
  if (!(temp_file = _wfopen(temp_filename, L"w")))
#endif  // _MSC_VER >= 1400
  {
    return false;
  }

  bool success = writer.WriteMap(temp_file);
  fclose(temp_file);
  if (!success) {
    _wunlink(temp_filename);
    return false;
  }

  *temp_file_path = temp_filename;

  return writer.GetModuleInfo(pdb_info);
}

__declspec(noreturn) void printUsageAndExit() {
  wprintf(L"Usage:\n\n"
          L"    symupload [--timeout NN] [--product product_name] ^\n"
          L"              <file.exe|file.dll> <symbol upload URL> ^\n"
          L"              [...<symbol upload URLs>]\n\n");
  wprintf(L"  - Timeout is in milliseconds, or can be 0 to be unlimited.\n");
  wprintf(L"  - product_name is an HTTP-friendly product name. It must only\n"
          L"    contain an ascii subset: alphanumeric and punctuation.\n"
          L"    This string is case-sensitive.\n\n");
  wprintf(L"Example:\n\n"
          L"    symupload.exe --timeout 0 --product Chrome ^\n"
          L"        chrome.dll http://no.free.symbol.server.for.you\n");
  exit(0);
}
int wmain(int argc, wchar_t *argv[]) {
  const wchar_t *module;
  const wchar_t *product = nullptr;
  int timeout = -1;
  int currentarg = 1;
  while (argc > currentarg + 1) {
    if (!wcscmp(L"--timeout", argv[currentarg])) {
      timeout = _wtoi(argv[currentarg + 1]);
      currentarg += 2;
      continue;
    }
    if (!wcscmp(L"--product", argv[currentarg])) {
      product = argv[currentarg + 1];
      currentarg += 2;
      continue;
    }
    break;
  }

  if (argc >= currentarg + 2)
    module = argv[currentarg++];
  else
    printUsageAndExit();

  wstring symbol_file;
  PDBModuleInfo pdb_info;
  if (!DumpSymbolsToTempFile(module, &symbol_file, &pdb_info)) {
    fwprintf(stderr, L"Could not get symbol data from %s\n", module);
    return 1;
  }

  wstring code_file = WindowsStringUtils::GetBaseName(wstring(module));

  map<wstring, wstring> parameters;
  parameters[L"code_file"] = code_file;
  parameters[L"debug_file"] = pdb_info.debug_file;
  parameters[L"debug_identifier"] = pdb_info.debug_identifier;
  parameters[L"os"] = L"windows";  // This version of symupload is Windows-only
  parameters[L"cpu"] = pdb_info.cpu;

  // Don't make a missing product name a hard error.  Issue a warning and let
  // the server decide whether to reject files without product name.
  if (product) {
    parameters[L"product"] = product;
  } else {
    fwprintf(
        stderr,
        L"Warning: No product name (flag --product) was specified for %s\n",
        module);
  }

  // Don't make a missing version a hard error.  Issue a warning, and let the
  // server decide whether to reject files without versions.
  wstring file_version;
  if (GetFileVersionString(module, &file_version)) {
    parameters[L"version"] = file_version;
  } else {
    fwprintf(stderr, L"Warning: Could not get file version for %s\n", module);
  }

  map<wstring, wstring> files;
  files[L"symbol_file"] = symbol_file;

  bool success = true;

  while (currentarg < argc) {
    int response_code;
    if (!HTTPUpload::SendRequest(argv[currentarg], parameters, files,
                                 timeout == -1 ? NULL : &timeout,
                                 nullptr, &response_code)) {
      success = false;
      fwprintf(stderr,
               L"Symbol file upload to %s failed. Response code = %ld\n",
               argv[currentarg], response_code);
    }
    currentarg++;
  }

  _wunlink(symbol_file.c_str());

  if (success) {
    wprintf(L"Uploaded symbols for windows-%s/%s/%s (%s %s)\n",
            pdb_info.cpu.c_str(), pdb_info.debug_file.c_str(),
            pdb_info.debug_identifier.c_str(), code_file.c_str(),
            file_version.c_str());
  }

  return success ? 0 : 1;
}
<commit_msg>Change symbol upload message to include 'breakpad'<commit_after>// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Tool to upload an exe/dll and its associated symbols to an HTTP server.
// The PDB file is located automatically, using the path embedded in the
// executable.  The upload is sent as a multipart/form-data POST request,
// with the following parameters:
//  code_file: the basename of the module, e.g. "app.exe"
//  debug_file: the basename of the debugging file, e.g. "app.pdb"
//  debug_identifier: the debug file's identifier, usually consisting of
//                    the guid and age embedded in the pdb, e.g.
//                    "11111111BBBB3333DDDD555555555555F"
//  product: the HTTP-friendly product name, e.g. "MyApp"
//  version: the file version of the module, e.g. "1.2.3.4"
//  os: the operating system that the module was built for, always
//      "windows" in this implementation.
//  cpu: the CPU that the module was built for, typically "x86".
//  symbol_file: the contents of the breakpad-format symbol file

#include <windows.h>
#include <dbghelp.h>
#include <wininet.h>

#include <cstdio>
#include <map>
#include <string>
#include <vector>

#include "common/windows/string_utils-inl.h"

#include "common/windows/http_upload.h"
#include "common/windows/pdb_source_line_writer.h"

using std::string;
using std::wstring;
using std::vector;
using std::map;
using google_breakpad::HTTPUpload;
using google_breakpad::PDBModuleInfo;
using google_breakpad::PDBSourceLineWriter;
using google_breakpad::WindowsStringUtils;

// Extracts the file version information for the given filename,
// as a string, for example, "1.2.3.4".  Returns true on success.
static bool GetFileVersionString(const wchar_t *filename, wstring *version) {
  DWORD handle;
  DWORD version_size = GetFileVersionInfoSize(filename, &handle);
  if (version_size < sizeof(VS_FIXEDFILEINFO)) {
    return false;
  }

  vector<char> version_info(version_size);
  if (!GetFileVersionInfo(filename, handle, version_size, &version_info[0])) {
    return false;
  }

  void *file_info_buffer = NULL;
  unsigned int file_info_length;
  if (!VerQueryValue(&version_info[0], L"\\",
                     &file_info_buffer, &file_info_length)) {
    return false;
  }

  // The maximum value of each version component is 65535 (0xffff),
  // so the max length is 24, including the terminating null.
  wchar_t ver_string[24];
  VS_FIXEDFILEINFO *file_info =
    reinterpret_cast<VS_FIXEDFILEINFO*>(file_info_buffer);
  swprintf(ver_string, sizeof(ver_string) / sizeof(ver_string[0]),
           L"%d.%d.%d.%d",
           file_info->dwFileVersionMS >> 16,
           file_info->dwFileVersionMS & 0xffff,
           file_info->dwFileVersionLS >> 16,
           file_info->dwFileVersionLS & 0xffff);

  // remove when VC++7.1 is no longer supported
  ver_string[sizeof(ver_string) / sizeof(ver_string[0]) - 1] = L'\0';

  *version = ver_string;
  return true;
}

// Creates a new temporary file and writes the symbol data from the given
// exe/dll file to it.  Returns the path to the temp file in temp_file_path
// and information about the pdb in pdb_info.
static bool DumpSymbolsToTempFile(const wchar_t *file,
                                  wstring *temp_file_path,
                                  PDBModuleInfo *pdb_info) {
  google_breakpad::PDBSourceLineWriter writer;
  // Use EXE_FILE to get information out of the exe/dll in addition to the
  // pdb.  The name and version number of the exe/dll are of value, and
  // there's no way to locate an exe/dll given a pdb.
  if (!writer.Open(file, PDBSourceLineWriter::EXE_FILE)) {
    return false;
  }

  wchar_t temp_path[_MAX_PATH];
  if (GetTempPath(_MAX_PATH, temp_path) == 0) {
    return false;
  }

  wchar_t temp_filename[_MAX_PATH];
  if (GetTempFileName(temp_path, L"sym", 0, temp_filename) == 0) {
    return false;
  }

  FILE *temp_file = NULL;
#if _MSC_VER >= 1400  // MSVC 2005/8
  if (_wfopen_s(&temp_file, temp_filename, L"w") != 0)
#else  // _MSC_VER >= 1400
  // _wfopen_s was introduced in MSVC8.  Use _wfopen for earlier environments.
  // Don't use it with MSVC8 and later, because it's deprecated.
  if (!(temp_file = _wfopen(temp_filename, L"w")))
#endif  // _MSC_VER >= 1400
  {
    return false;
  }

  bool success = writer.WriteMap(temp_file);
  fclose(temp_file);
  if (!success) {
    _wunlink(temp_filename);
    return false;
  }

  *temp_file_path = temp_filename;

  return writer.GetModuleInfo(pdb_info);
}

__declspec(noreturn) void printUsageAndExit() {
  wprintf(L"Usage:\n\n"
          L"    symupload [--timeout NN] [--product product_name] ^\n"
          L"              <file.exe|file.dll> <symbol upload URL> ^\n"
          L"              [...<symbol upload URLs>]\n\n");
  wprintf(L"  - Timeout is in milliseconds, or can be 0 to be unlimited.\n");
  wprintf(L"  - product_name is an HTTP-friendly product name. It must only\n"
          L"    contain an ascii subset: alphanumeric and punctuation.\n"
          L"    This string is case-sensitive.\n\n");
  wprintf(L"Example:\n\n"
          L"    symupload.exe --timeout 0 --product Chrome ^\n"
          L"        chrome.dll http://no.free.symbol.server.for.you\n");
  exit(0);
}
int wmain(int argc, wchar_t *argv[]) {
  const wchar_t *module;
  const wchar_t *product = nullptr;
  int timeout = -1;
  int currentarg = 1;
  while (argc > currentarg + 1) {
    if (!wcscmp(L"--timeout", argv[currentarg])) {
      timeout = _wtoi(argv[currentarg + 1]);
      currentarg += 2;
      continue;
    }
    if (!wcscmp(L"--product", argv[currentarg])) {
      product = argv[currentarg + 1];
      currentarg += 2;
      continue;
    }
    break;
  }

  if (argc >= currentarg + 2)
    module = argv[currentarg++];
  else
    printUsageAndExit();

  wstring symbol_file;
  PDBModuleInfo pdb_info;
  if (!DumpSymbolsToTempFile(module, &symbol_file, &pdb_info)) {
    fwprintf(stderr, L"Could not get symbol data from %s\n", module);
    return 1;
  }

  wstring code_file = WindowsStringUtils::GetBaseName(wstring(module));

  map<wstring, wstring> parameters;
  parameters[L"code_file"] = code_file;
  parameters[L"debug_file"] = pdb_info.debug_file;
  parameters[L"debug_identifier"] = pdb_info.debug_identifier;
  parameters[L"os"] = L"windows";  // This version of symupload is Windows-only
  parameters[L"cpu"] = pdb_info.cpu;

  // Don't make a missing product name a hard error.  Issue a warning and let
  // the server decide whether to reject files without product name.
  if (product) {
    parameters[L"product"] = product;
  } else {
    fwprintf(
        stderr,
        L"Warning: No product name (flag --product) was specified for %s\n",
        module);
  }

  // Don't make a missing version a hard error.  Issue a warning, and let the
  // server decide whether to reject files without versions.
  wstring file_version;
  if (GetFileVersionString(module, &file_version)) {
    parameters[L"version"] = file_version;
  } else {
    fwprintf(stderr, L"Warning: Could not get file version for %s\n", module);
  }

  map<wstring, wstring> files;
  files[L"symbol_file"] = symbol_file;

  bool success = true;

  while (currentarg < argc) {
    int response_code;
    if (!HTTPUpload::SendRequest(argv[currentarg], parameters, files,
                                 timeout == -1 ? NULL : &timeout,
                                 nullptr, &response_code)) {
      success = false;
      fwprintf(stderr,
               L"Symbol file upload to %s failed. Response code = %ld\n",
               argv[currentarg], response_code);
    }
    currentarg++;
  }

  _wunlink(symbol_file.c_str());

  if (success) {
    wprintf(L"Uploaded breakpad symbols for windows-%s/%s/%s (%s %s)\n",
            pdb_info.cpu.c_str(), pdb_info.debug_file.c_str(),
            pdb_info.debug_identifier.c_str(), code_file.c_str(),
            file_version.c_str());
  }

  return success ? 0 : 1;
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2014-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

// @Generated by gentest/gentest.rb from gentest/fixtures/YGPercentageTest.html

#include <gtest/gtest.h>
#include <yoga/Yoga.h>

TEST(YogaTest, cloning_shared_root) {
  const YGConfigRef config = YGConfigNew();

  const YGNodeRef root = YGNodeNewWithConfig(config);
  YGNodeStyleSetWidth(root, 100);
  YGNodeStyleSetHeight(root, 100);

  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
  YGNodeStyleSetFlexGrow(root_child0, 1);
  YGNodeStyleSetFlexBasis(root_child0, 50);
  YGNodeInsertChild(root, root_child0, 0);

  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
  YGNodeStyleSetFlexGrow(root_child1, 1);
  YGNodeInsertChild(root, root_child1, 1);
  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);

  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));

  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child0));

  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child1));
  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));

  const YGNodeRef root2 = YGNodeClone(root);
  YGNodeStyleSetWidth(root2, 100);

  ASSERT_EQ(2, YGNodeGetChildCount(root2));
  // The children should have referential equality at this point.
  ASSERT_EQ(root_child0, YGNodeGetChild(root2, 0));
  ASSERT_EQ(root_child1, YGNodeGetChild(root2, 1));

  YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);

  ASSERT_EQ(2, YGNodeGetChildCount(root2));
  // Relayout with no changed input should result in referential equality.
  ASSERT_EQ(root_child0, YGNodeGetChild(root2, 0));
  ASSERT_EQ(root_child1, YGNodeGetChild(root2, 1));

  YGNodeStyleSetWidth(root2, 150);
  YGNodeStyleSetHeight(root2, 200);
  YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);

  ASSERT_EQ(2, YGNodeGetChildCount(root2));
  // Relayout with changed input should result in cloned children.
  const YGNodeRef root2_child0 = YGNodeGetChild(root2, 0);
  const YGNodeRef root2_child1 = YGNodeGetChild(root2, 1);
  ASSERT_NE(root_child0, root2_child0);
  ASSERT_NE(root_child1, root2_child1);

  // Everything in the root should remain unchanged.
  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));

  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child0));

  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child1));
  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));

  // The new root now has new layout.
  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root2));
  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root2));
  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root2));
  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root2));

  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root2_child0));
  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root2_child0));
  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root2_child0));
  ASSERT_FLOAT_EQ(125, YGNodeLayoutGetHeight(root2_child0));

  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root2_child1));
  ASSERT_FLOAT_EQ(125, YGNodeLayoutGetTop(root2_child1));
  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root2_child1));
  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root2_child1));

  YGNodeFreeRecursive(root2);

  YGNodeFreeRecursive(root);

  YGConfigFree(config);
}

TEST(YogaTest, mutating_children_of_a_clone_clones) {
  const YGConfigRef config = YGConfigNew();

  const YGNodeRef root = YGNodeNewWithConfig(config);
  ASSERT_EQ(0, YGNodeGetChildCount(root));

  const YGNodeRef root2 = YGNodeClone(root);
  ASSERT_EQ(0, YGNodeGetChildCount(root2));

  const YGNodeRef root2_child0 = YGNodeNewWithConfig(config);
  YGNodeInsertChild(root2, root2_child0, 0);

  ASSERT_EQ(0, YGNodeGetChildCount(root));
  ASSERT_EQ(1, YGNodeGetChildCount(root2));

  const YGNodeRef root3 = YGNodeClone(root2);
  ASSERT_EQ(1, YGNodeGetChildCount(root2));
  ASSERT_EQ(1, YGNodeGetChildCount(root3));
  ASSERT_EQ(YGNodeGetChild(root2, 0), YGNodeGetChild(root3, 0));

  const YGNodeRef root3_child1 = YGNodeNewWithConfig(config);
  YGNodeInsertChild(root3, root3_child1, 1);
  ASSERT_EQ(1, YGNodeGetChildCount(root2));
  ASSERT_EQ(2, YGNodeGetChildCount(root3));
  ASSERT_EQ(root3_child1, YGNodeGetChild(root3, 1));
  ASSERT_NE(YGNodeGetChild(root2, 0), YGNodeGetChild(root3, 0));

  const YGNodeRef root4 = YGNodeClone(root3);
  ASSERT_EQ(root3_child1, YGNodeGetChild(root4, 1));

  YGNodeRemoveChild(root4, root3_child1);
  ASSERT_EQ(2, YGNodeGetChildCount(root3));
  ASSERT_EQ(1, YGNodeGetChildCount(root4));
  ASSERT_NE(YGNodeGetChild(root3, 0), YGNodeGetChild(root4, 0));

  YGNodeFreeRecursive(root4);
  YGNodeFreeRecursive(root3);
  YGNodeFreeRecursive(root2);
  YGNodeFreeRecursive(root);

  YGConfigFree(config);
}

TEST(YogaTest, cloning_two_levels) {
  const YGConfigRef config = YGConfigNew();

  const YGNodeRef root = YGNodeNewWithConfig(config);
  YGNodeStyleSetWidth(root, 100);
  YGNodeStyleSetHeight(root, 100);

  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
  YGNodeStyleSetFlexGrow(root_child0, 1);
  YGNodeStyleSetFlexBasis(root_child0, 15);
  YGNodeInsertChild(root, root_child0, 0);

  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
  YGNodeStyleSetFlexGrow(root_child1, 1);
  YGNodeInsertChild(root, root_child1, 1);

  const YGNodeRef root_child1_0 = YGNodeNewWithConfig(config);
  YGNodeStyleSetFlexBasis(root_child1_0, 10);
  YGNodeStyleSetFlexGrow(root_child1_0, 1);
  YGNodeInsertChild(root_child1, root_child1_0, 0);

  const YGNodeRef root_child1_1 = YGNodeNewWithConfig(config);
  YGNodeStyleSetFlexBasis(root_child1_1, 25);
  YGNodeInsertChild(root_child1, root_child1_1, 1);

  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);

  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child1));
  ASSERT_FLOAT_EQ(35, YGNodeLayoutGetHeight(root_child1_0));
  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1_1));

  const YGNodeRef root2_child0 = YGNodeClone(root_child0);
  const YGNodeRef root2_child1 = YGNodeClone(root_child1);
  const YGNodeRef root2 = YGNodeClone(root);

  YGNodeStyleSetFlexGrow(root2_child0, 0);
  YGNodeStyleSetFlexBasis(root2_child0, 40);

  YGNodeRemoveAllChildren(root2);
  YGNodeInsertChild(root2, root2_child0, 0);
  YGNodeInsertChild(root2, root2_child1, 1);
  ASSERT_EQ(2, YGNodeGetChildCount(root2));

  YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);

  // Original root is unchanged
  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child1));
  ASSERT_FLOAT_EQ(35, YGNodeLayoutGetHeight(root_child1_0));
  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1_1));

  // New root has new layout at the top
  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root2_child0));
  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root2_child1));

  // The deeper children are untouched.
  ASSERT_EQ(YGNodeGetChild(root2_child1, 0), root_child1_0);
  ASSERT_EQ(YGNodeGetChild(root2_child1, 1), root_child1_1);

  YGNodeFreeRecursive(root2);
  YGNodeFreeRecursive(root);

  YGConfigFree(config);
}

TEST(YogaTest, cloning_and_freeing) {
  const int32_t initialInstanceCount = YGNodeGetInstanceCount();

  const YGConfigRef config = YGConfigNew();

  const YGNodeRef root = YGNodeNewWithConfig(config);
  YGNodeStyleSetWidth(root, 100);
  YGNodeStyleSetHeight(root, 100);
  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
  YGNodeInsertChild(root, root_child0, 0);
  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
  YGNodeInsertChild(root, root_child1, 1);

  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);

  const YGNodeRef root2 = YGNodeClone(root);

  // Freeing the original root should be safe as long as we don't free its
  // children.
  YGNodeFree(root);

  YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);

  YGNodeFreeRecursive(root2);

  YGNodeFree(root_child0);
  YGNodeFree(root_child1);

  YGConfigFree(config);

  ASSERT_EQ(initialInstanceCount, YGNodeGetInstanceCount());
}
<commit_msg>Removed misleading comment in YGPersistenceTest<commit_after>/**
 * Copyright (c) 2014-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include <gtest/gtest.h>
#include <yoga/Yoga.h>

TEST(YogaTest, cloning_shared_root) {
  const YGConfigRef config = YGConfigNew();

  const YGNodeRef root = YGNodeNewWithConfig(config);
  YGNodeStyleSetWidth(root, 100);
  YGNodeStyleSetHeight(root, 100);

  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
  YGNodeStyleSetFlexGrow(root_child0, 1);
  YGNodeStyleSetFlexBasis(root_child0, 50);
  YGNodeInsertChild(root, root_child0, 0);

  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
  YGNodeStyleSetFlexGrow(root_child1, 1);
  YGNodeInsertChild(root, root_child1, 1);
  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);

  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));

  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child0));

  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child1));
  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));

  const YGNodeRef root2 = YGNodeClone(root);
  YGNodeStyleSetWidth(root2, 100);

  ASSERT_EQ(2, YGNodeGetChildCount(root2));
  // The children should have referential equality at this point.
  ASSERT_EQ(root_child0, YGNodeGetChild(root2, 0));
  ASSERT_EQ(root_child1, YGNodeGetChild(root2, 1));

  YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);

  ASSERT_EQ(2, YGNodeGetChildCount(root2));
  // Relayout with no changed input should result in referential equality.
  ASSERT_EQ(root_child0, YGNodeGetChild(root2, 0));
  ASSERT_EQ(root_child1, YGNodeGetChild(root2, 1));

  YGNodeStyleSetWidth(root2, 150);
  YGNodeStyleSetHeight(root2, 200);
  YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);

  ASSERT_EQ(2, YGNodeGetChildCount(root2));
  // Relayout with changed input should result in cloned children.
  const YGNodeRef root2_child0 = YGNodeGetChild(root2, 0);
  const YGNodeRef root2_child1 = YGNodeGetChild(root2, 1);
  ASSERT_NE(root_child0, root2_child0);
  ASSERT_NE(root_child1, root2_child1);

  // Everything in the root should remain unchanged.
  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));

  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child0));

  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child1));
  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));

  // The new root now has new layout.
  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root2));
  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root2));
  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root2));
  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root2));

  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root2_child0));
  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root2_child0));
  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root2_child0));
  ASSERT_FLOAT_EQ(125, YGNodeLayoutGetHeight(root2_child0));

  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root2_child1));
  ASSERT_FLOAT_EQ(125, YGNodeLayoutGetTop(root2_child1));
  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root2_child1));
  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root2_child1));

  YGNodeFreeRecursive(root2);

  YGNodeFreeRecursive(root);

  YGConfigFree(config);
}

TEST(YogaTest, mutating_children_of_a_clone_clones) {
  const YGConfigRef config = YGConfigNew();

  const YGNodeRef root = YGNodeNewWithConfig(config);
  ASSERT_EQ(0, YGNodeGetChildCount(root));

  const YGNodeRef root2 = YGNodeClone(root);
  ASSERT_EQ(0, YGNodeGetChildCount(root2));

  const YGNodeRef root2_child0 = YGNodeNewWithConfig(config);
  YGNodeInsertChild(root2, root2_child0, 0);

  ASSERT_EQ(0, YGNodeGetChildCount(root));
  ASSERT_EQ(1, YGNodeGetChildCount(root2));

  const YGNodeRef root3 = YGNodeClone(root2);
  ASSERT_EQ(1, YGNodeGetChildCount(root2));
  ASSERT_EQ(1, YGNodeGetChildCount(root3));
  ASSERT_EQ(YGNodeGetChild(root2, 0), YGNodeGetChild(root3, 0));

  const YGNodeRef root3_child1 = YGNodeNewWithConfig(config);
  YGNodeInsertChild(root3, root3_child1, 1);
  ASSERT_EQ(1, YGNodeGetChildCount(root2));
  ASSERT_EQ(2, YGNodeGetChildCount(root3));
  ASSERT_EQ(root3_child1, YGNodeGetChild(root3, 1));
  ASSERT_NE(YGNodeGetChild(root2, 0), YGNodeGetChild(root3, 0));

  const YGNodeRef root4 = YGNodeClone(root3);
  ASSERT_EQ(root3_child1, YGNodeGetChild(root4, 1));

  YGNodeRemoveChild(root4, root3_child1);
  ASSERT_EQ(2, YGNodeGetChildCount(root3));
  ASSERT_EQ(1, YGNodeGetChildCount(root4));
  ASSERT_NE(YGNodeGetChild(root3, 0), YGNodeGetChild(root4, 0));

  YGNodeFreeRecursive(root4);
  YGNodeFreeRecursive(root3);
  YGNodeFreeRecursive(root2);
  YGNodeFreeRecursive(root);

  YGConfigFree(config);
}

TEST(YogaTest, cloning_two_levels) {
  const YGConfigRef config = YGConfigNew();

  const YGNodeRef root = YGNodeNewWithConfig(config);
  YGNodeStyleSetWidth(root, 100);
  YGNodeStyleSetHeight(root, 100);

  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
  YGNodeStyleSetFlexGrow(root_child0, 1);
  YGNodeStyleSetFlexBasis(root_child0, 15);
  YGNodeInsertChild(root, root_child0, 0);

  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
  YGNodeStyleSetFlexGrow(root_child1, 1);
  YGNodeInsertChild(root, root_child1, 1);

  const YGNodeRef root_child1_0 = YGNodeNewWithConfig(config);
  YGNodeStyleSetFlexBasis(root_child1_0, 10);
  YGNodeStyleSetFlexGrow(root_child1_0, 1);
  YGNodeInsertChild(root_child1, root_child1_0, 0);

  const YGNodeRef root_child1_1 = YGNodeNewWithConfig(config);
  YGNodeStyleSetFlexBasis(root_child1_1, 25);
  YGNodeInsertChild(root_child1, root_child1_1, 1);

  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);

  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child1));
  ASSERT_FLOAT_EQ(35, YGNodeLayoutGetHeight(root_child1_0));
  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1_1));

  const YGNodeRef root2_child0 = YGNodeClone(root_child0);
  const YGNodeRef root2_child1 = YGNodeClone(root_child1);
  const YGNodeRef root2 = YGNodeClone(root);

  YGNodeStyleSetFlexGrow(root2_child0, 0);
  YGNodeStyleSetFlexBasis(root2_child0, 40);

  YGNodeRemoveAllChildren(root2);
  YGNodeInsertChild(root2, root2_child0, 0);
  YGNodeInsertChild(root2, root2_child1, 1);
  ASSERT_EQ(2, YGNodeGetChildCount(root2));

  YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);

  // Original root is unchanged
  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child1));
  ASSERT_FLOAT_EQ(35, YGNodeLayoutGetHeight(root_child1_0));
  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1_1));

  // New root has new layout at the top
  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root2_child0));
  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root2_child1));

  // The deeper children are untouched.
  ASSERT_EQ(YGNodeGetChild(root2_child1, 0), root_child1_0);
  ASSERT_EQ(YGNodeGetChild(root2_child1, 1), root_child1_1);

  YGNodeFreeRecursive(root2);
  YGNodeFreeRecursive(root);

  YGConfigFree(config);
}

TEST(YogaTest, cloning_and_freeing) {
  const int32_t initialInstanceCount = YGNodeGetInstanceCount();

  const YGConfigRef config = YGConfigNew();

  const YGNodeRef root = YGNodeNewWithConfig(config);
  YGNodeStyleSetWidth(root, 100);
  YGNodeStyleSetHeight(root, 100);
  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
  YGNodeInsertChild(root, root_child0, 0);
  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
  YGNodeInsertChild(root, root_child1, 1);

  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);

  const YGNodeRef root2 = YGNodeClone(root);

  // Freeing the original root should be safe as long as we don't free its
  // children.
  YGNodeFree(root);

  YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);

  YGNodeFreeRecursive(root2);

  YGNodeFree(root_child0);
  YGNodeFree(root_child1);

  YGConfigFree(config);

  ASSERT_EQ(initialInstanceCount, YGNodeGetInstanceCount());
}
<|endoftext|>


<commit_before>#pragma once

#include <microscopes/common/assert.hpp>

namespace lda_util {

    inline bool
    valid_probability_vector(const std::vector<float> &p){
        float sum = 0;
        for(auto x: p){
            if(isfinite(x) == false) return false;
            if(x < 0) return false;
            sum+=x;
        }
        return (std::abs(1 - sum) < 0.01);
    }

    template<typename T> void
    removeFirst(std::vector<T> &v, T element){
        auto it = std::find(v.begin(),v.end(), element);
        if (it != v.end()) {
          v.erase(it);
        }
    }

    // http://stackoverflow.com/a/1267878/982745
    template< class T >
    std::vector<T>
    selectByIndex(const std::vector<T> &v, const std::vector<size_t> &index )  {
        std::vector<T> new_v;
        new_v.reserve(index.size());
        for(size_t i: index){
            new_v.push_back(v[i]);
        }

        return new_v;
    }

    template<class T>
    void
    normalize(std::vector<T> &v){
        Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, 1>> vec(v.data(), v.size());
        vec /= vec.sum();
    }

    template<class T, class J>
    class defaultdict{
        J default_value;
        std::map<T, J> map;
    public:
        defaultdict(J val){
            default_value = val;
            map = std::map<T, J>();
        }

        J get(T t) {
            if(map.count(t) > 0){
                return map[t];
            }
            else{
                return default_value;
            }
        }

        void
        set(T t, J j){
            map[t] = j;
        }

        void
        incr(T t, J by){
            if(map.count(t) > 0){
                map[t] += by;
            }
            else{
                map[t] = by + default_value;
            }
        }

        void
        decr(T t, J by){
            if(map.count(t) > 0){
                map[t] -= by;
            }
            else{
                map[t] = default_value - by;
            }
        }

        bool
        contains(T t){
            return map.count(t) > 0;
        }
    };
}<commit_msg>isfinite is in math.h<commit_after>#pragma once

#include <math.h>

namespace lda_util {

    inline bool
    valid_probability_vector(const std::vector<float> &p){
        float sum = 0;
        for(auto x: p){
            if(std::isfinite(x) == false) return false;
            if(x < 0) return false;
            sum+=x;
        }
        return (std::abs(1 - sum) < 0.01);
    }

    template<typename T> void
    removeFirst(std::vector<T> &v, T element){
        auto it = std::find(v.begin(),v.end(), element);
        if (it != v.end()) {
          v.erase(it);
        }
    }

    // http://stackoverflow.com/a/1267878/982745
    template< class T >
    std::vector<T>
    selectByIndex(const std::vector<T> &v, const std::vector<size_t> &index )  {
        std::vector<T> new_v;
        new_v.reserve(index.size());
        for(size_t i: index){
            new_v.push_back(v[i]);
        }

        return new_v;
    }

    template<class T>
    void
    normalize(std::vector<T> &v){
        Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, 1>> vec(v.data(), v.size());
        vec /= vec.sum();
    }

    template<class T, class J>
    class defaultdict{
        J default_value;
        std::map<T, J> map;
    public:
        defaultdict(J val){
            default_value = val;
            map = std::map<T, J>();
        }

        J get(T t) {
            if(map.count(t) > 0){
                return map[t];
            }
            else{
                return default_value;
            }
        }

        void
        set(T t, J j){
            map[t] = j;
        }

        void
        incr(T t, J by){
            if(map.count(t) > 0){
                map[t] += by;
            }
            else{
                map[t] = by + default_value;
            }
        }

        void
        decr(T t, J by){
            if(map.count(t) > 0){
                map[t] -= by;
            }
            else{
                map[t] = default_value - by;
            }
        }

        bool
        contains(T t){
            return map.count(t) > 0;
        }
    };
}<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip>
#include <string>
#include <pcrecpp.h>

#include "net/net.h"

extern "C" {
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/if_ether.h>
}

static inline std::string ipv4addressToString(const void * src) {
  char ip[INET_ADDRSTRLEN];
  inet_ntop(AF_INET, src, ip, INET_ADDRSTRLEN);
  return std::string(ip);
}

namespace mckeys {

using namespace std;

// Like getInstance. Used for creating commands from packets.
MemcacheCommand MemcacheCommand::create(const Packet& pkt,
                                        const bpf_u_int32 captureAddress,
                                        const memcache_command_t expectedCmdType)
{
  static ssize_t ether_header_sz = sizeof(struct ether_header);
  static ssize_t ip_sz = sizeof(struct ip);

  const struct ether_header* ethernetHeader;
  const struct ip* ipHeader;
  const struct tcphdr* tcpHeader;

  const Packet::Header* pkthdr = &pkt.getHeader();
  const Packet::Data* packet = pkt.getData();

  u_char *data;
  uint32_t dataLength = 0;
  uint32_t dataOffset;

  string sourceAddress = "";
  string destinationAddress = "";

  // must be an IP packet
  // TODO add support for dumping localhost
  ethernetHeader = (struct ether_header*)packet;
  auto etype = ntohs(ethernetHeader->ether_type);
  if (etype != ETHERTYPE_IP) {
    return MemcacheCommand();
  }

  // must be TCP - TODO add support for UDP
  ipHeader = (struct ip*)(packet + ether_header_sz);
  auto itype = ipHeader->ip_p;
  if (itype != IPPROTO_TCP) {
    return MemcacheCommand();
  }
  sourceAddress = ipv4addressToString(&(ipHeader->ip_src));
  destinationAddress = ipv4addressToString(&(ipHeader->ip_dst));

  tcpHeader = (struct tcphdr*)(packet + ether_header_sz + ip_sz);
  dataOffset = ether_header_sz + ip_sz + (tcpHeader->doff * 4);
  data = (u_char*)(packet + dataOffset);
  dataLength = pkthdr->len - dataOffset;
  if (dataLength > pkthdr->caplen) {
    dataLength = pkthdr->caplen;
  }

  // The packet was destined for our capture address, this is a request
  // This bit of optimization lets us ignore a reasonably large percentage of
  // traffic
  if (expectedCmdType == MC_REQUEST) {
    if (ipHeader->ip_dst.s_addr == captureAddress) { // a request packet to server
      return makeRequestCommand(data, dataLength, sourceAddress, destinationAddress);
    }
  } else if (expectedCmdType == MC_RESPONSE) {
    if (ipHeader->ip_src.s_addr == captureAddress) { // a response packet from server
      return makeResponseCommand(data, dataLength, sourceAddress, destinationAddress);
    }
  }
  return MemcacheCommand();
}

// protected default constructor
MemcacheCommand::MemcacheCommand()
  : cmdType_(MC_UNKNOWN),
    sourceAddress_(),
    destinationAddress_(),
    commandName_(),
    objectKey_(),
    objectSize_(0)
{}

// protected constructor
MemcacheCommand::MemcacheCommand(const memcache_command_t cmdType,
                                 const string sourceAddress,
                                 const string destinationAddress,
                                 const string commandName,
                                 const string objectKey,
                                 uint32_t objectSize)
    : cmdType_(cmdType),
      sourceAddress_(sourceAddress),
      destinationAddress_(destinationAddress),
      commandName_(commandName),
      objectKey_(objectKey),
      objectSize_(objectSize)
{}

// static protected
MemcacheCommand MemcacheCommand::makeRequestCommand(u_char* data,
                                                    int length,
                                                    string sourceAddress,
                                                    string destinationAddress)
{
  // set <key> <flags> <exptime> <bytes> [noreply]\r\n
  static string commandName = "set";
  static pcrecpp::RE re(commandName + string(" (\\S+) \\d+ \\d+ (\\d+)"),
                        pcrecpp::RE_Options(PCRE_MULTILINE));
  string key;
  int size = -1;

  if (length < 11) { // set k 0 0 1
    return MemcacheCommand();
  }
  for (int i = 0; i < length; i++) {
    int cid = (int)data[i];
    if (!(isprint(cid) || cid == 10 || cid == 13)) {
      return MemcacheCommand();
    }
  }

  string input = string((char*)data, length);
  re.PartialMatch(input, &key, &size);
  if (size >= 0) {
    return MemcacheCommand(MC_REQUEST, sourceAddress, destinationAddress, commandName, key, size);
  }
  return MemcacheCommand();
}

// static protected
MemcacheCommand MemcacheCommand::makeResponseCommand(u_char *data,
                                                     int length,
                                                     string sourceAddress,
                                                     string destinationAddress)
{
  // VALUE <key> <flags> <bytes> [<cas unique>]\r\n
  static string commandName = "get";
  static pcrecpp::RE re("VALUE (\\S+) \\d+ (\\d+)",
                        pcrecpp::RE_Options(PCRE_MULTILINE));
  string key;
  int size = -1;

  if (length < 11) { // VALUE k 0 1
    return MemcacheCommand();
  }
  for (int i = 0; i < length; i++) {
    int cid = (int)data[i];
    if (!(isprint(cid) || cid == 10 || cid == 13)) {
      return MemcacheCommand();
    }
  }

  string input = string((char*)data, length);
  re.PartialMatch(input, &key, &size);
  if (size >= 0) {
    return MemcacheCommand(MC_RESPONSE, sourceAddress, destinationAddress, commandName, key, size);
  } else {
    return MemcacheCommand();
  }
}

} // end namespace
<commit_msg>Fix packet parsing<commit_after>#include <iostream>
#include <iomanip>
#include <string>
#include <pcrecpp.h>

#include "net/net.h"

extern "C" {
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/if_ether.h>
}

static inline std::string ipv4addressToString(const void * src) {
  char ip[INET_ADDRSTRLEN];
  inet_ntop(AF_INET, src, ip, INET_ADDRSTRLEN);
  return std::string(ip);
}

namespace mckeys {

using namespace std;

// Like getInstance. Used for creating commands from packets.
MemcacheCommand MemcacheCommand::create(const Packet& pkt,
                                        const bpf_u_int32 captureAddress,
                                        const memcache_command_t expectedCmdType)
{
  static ssize_t ether_header_sz = sizeof(struct ether_header);
  static ssize_t ip_sz = sizeof(struct ip);

  const struct ether_header* ethernetHeader;
  const struct ip* ipHeader;
  const struct tcphdr* tcpHeader;

  const Packet::Header* pkthdr = &pkt.getHeader();
  const Packet::Data* packet = pkt.getData();

  u_char *data;
  uint32_t dataLength = 0;
  uint32_t dataOffset;

  string sourceAddress = "";
  string destinationAddress = "";

  // must be an IP packet
  // TODO add support for dumping localhost
  ethernetHeader = (struct ether_header*)packet;
  auto etype = ntohs(ethernetHeader->ether_type);
  if (etype != ETHERTYPE_IP) {
    return MemcacheCommand();
  }

  // must be TCP - TODO add support for UDP
  ipHeader = (struct ip*)(packet + ether_header_sz);
  auto itype = ipHeader->ip_p;
  if (itype != IPPROTO_TCP) {
    return MemcacheCommand();
  }
  sourceAddress = ipv4addressToString(&(ipHeader->ip_src));
  destinationAddress = ipv4addressToString(&(ipHeader->ip_dst));

  tcpHeader = (struct tcphdr*)(packet + ether_header_sz + ip_sz);
  dataOffset = ether_header_sz + ip_sz + (tcpHeader->doff * 4);
  data = (u_char*)(packet + dataOffset);
  dataLength = pkthdr->len - dataOffset;
  if (dataLength > pkthdr->caplen) {
    dataLength = pkthdr->caplen;
  }

  // The packet was destined for our capture address, this is a request
  // This bit of optimization lets us ignore a reasonably large percentage of
  // traffic
  if (expectedCmdType == MC_REQUEST) {
    if (ipHeader->ip_dst.s_addr == captureAddress) { // a request packet to server
      return makeRequestCommand(data, dataLength, sourceAddress, destinationAddress);
    }
  } else if (expectedCmdType == MC_RESPONSE) {
    if (ipHeader->ip_src.s_addr == captureAddress) { // a response packet from server
      return makeResponseCommand(data, dataLength, sourceAddress, destinationAddress);
    }
  }
  return MemcacheCommand();
}

// protected default constructor
MemcacheCommand::MemcacheCommand()
  : cmdType_(MC_UNKNOWN),
    sourceAddress_(),
    destinationAddress_(),
    commandName_(),
    objectKey_(),
    objectSize_(0)
{}

// protected constructor
MemcacheCommand::MemcacheCommand(const memcache_command_t cmdType,
                                 const string sourceAddress,
                                 const string destinationAddress,
                                 const string commandName,
                                 const string objectKey,
                                 uint32_t objectSize)
    : cmdType_(cmdType),
      sourceAddress_(sourceAddress),
      destinationAddress_(destinationAddress),
      commandName_(commandName),
      objectKey_(objectKey),
      objectSize_(objectSize)
{}

// static protected
MemcacheCommand MemcacheCommand::makeRequestCommand(u_char* data,
                                                    int length,
                                                    string sourceAddress,
                                                    string destinationAddress)
{
  // set <key> <flags> <exptime> <bytes> [noreply]\r\n
  static string commandName = "set";
  static pcrecpp::RE re(commandName + string(" (\\S+) \\d+ \\d+ (\\d+)"),
                        pcrecpp::RE_Options(PCRE_MULTILINE));
  string key;
  int size = -1;
  string input = "";

  for (int i = 0; i < length; i++) {
    int cid = (int)data[i];
    if (isprint(cid) || cid == 10 || cid == 13) {
      input += static_cast<char>(cid);
    }
  }
  if (input.length() < 11) { // set k 0 0 1
    return MemcacheCommand();
  }

  re.PartialMatch(input, &key, &size);
  if (size >= 0) {
    return MemcacheCommand(MC_REQUEST, sourceAddress, destinationAddress, commandName, key, size);
  }
  return MemcacheCommand();
}

// static protected
MemcacheCommand MemcacheCommand::makeResponseCommand(u_char *data,
                                                     int length,
                                                     string sourceAddress,
                                                     string destinationAddress)
{
  // VALUE <key> <flags> <bytes> [<cas unique>]\r\n
  static string commandName = "get";
  static pcrecpp::RE re("VALUE (\\S+) \\d+ (\\d+)",
                        pcrecpp::RE_Options(PCRE_MULTILINE));
  string key;
  int size = -1;
  string input = "";

  for (int i = 0; i < length; i++) {
    int cid = (int)data[i];
    if (isprint(cid) || cid == 10 || cid == 13) {
      input += static_cast<char>(cid);
    }
  }
  if (input.length() < 11) { // VALUE k 0 1
    return MemcacheCommand();
  }

  re.PartialMatch(input, &key, &size);
  if (size >= 0) {
    return MemcacheCommand(MC_RESPONSE, sourceAddress, destinationAddress, commandName, key, size);
  } else {
    return MemcacheCommand();
  }
}

} // end namespace
<|endoftext|>