void TCPConnectionManagerTest::test_send()
{
    // Use Case:
    // client requests a connection
    // expect client to be registered for any data
    StreamDataRequest req;
    DataSpec require;
    require.addStreamData("testData");
    req.addDataOption(require);

    QTcpSocket* client = _createClient();
    _sendRequest( client, req );
    QCoreApplication::processEvents();
    CPPUNIT_ASSERT_EQUAL( 1, _server->clientsForStream("testData") );
    TestDataBlob blob;
    blob.setData("sometestData");
    _server->send("testData",&blob);
    sleep(1);

    CPPUNIT_ASSERT( client->state() == QAbstractSocket::ConnectedState );
    boost::shared_ptr<ServerResponse> r = _clientProtocol->receive(*client);
    CPPUNIT_ASSERT( r->type() == ServerResponse::Blob );
    DataBlobResponse* res = static_cast<DataBlobResponse*>(r.get());
    CPPUNIT_ASSERT( res->dataName() == "testData" );
    CPPUNIT_ASSERT( res->blobClass() == "TestDataBlob" );
    TestDataBlob recvBlob;
    recvBlob.deserialise(*client, res->byteOrder());
    CPPUNIT_ASSERT(recvBlob == blob);

}
// Connect to Pelican Lofar and register requested data type
void PelicanBlobClient::connectToLofarPelican()
{
    while (_tcpSocket->state() == QAbstractSocket::UnconnectedState) {

        _tcpSocket->connectToHost(_server, _port);

        if (!_tcpSocket->waitForConnected(5000) ||
                _tcpSocket->state() == QAbstractSocket::UnconnectedState)
        {
            cerr << "PelicanBlobClient: Unable to connect to server ("
                 << _server.toStdString() << ":" << _port << ")" << endl;
            sleep(2);
            continue;
        }

        // Define the data type which the client will except and send request
        StreamDataRequest req;
        DataSpec require;
        require.setStreamData(_blobType);
        req.addDataOption(require);

        QByteArray data = _protocol->serialise(req);
        _tcpSocket -> write(data);
        _tcpSocket -> waitForBytesWritten(data.size());
        _tcpSocket -> flush();
    }
}
示例#3
0
/**
 * @details
 * adds a data requirement. If the appropriate adapter
 * has not already been added with setAdater() then
 * this method will attemp to create a suitable one.
 */
void DataTypes::addData( const DataSpec& data )
{
    _dataRequirements.append(data);
    const QHash<QString,QString>& defaultAdapters = data.getAdapterTypes();
    _addData( data.serviceData(), defaultAdapters, AbstractAdapter::Service );
    _addData( data.streamData(), defaultAdapters, AbstractAdapter::Stream );
}
示例#4
0
void DataSpecTest::test_hash()
{
    // Use Case:
    // Ensure hash returns a non-zero value.
    {
        DataSpec d;
        d.addStreamData(QString("hello"));
        CPPUNIT_ASSERT(d.hash() != 0);
    }

    // Use Case:
    // Ensure different DataRequirement objects return different hash values.
    {
        DataSpec d1;
        d1.addStreamData(QString("one"));
        DataSpec d2;
        d2.addStreamData(QString("two"));
        CPPUNIT_ASSERT(d1.hash() != d2.hash());
    }

    // Use Case:
    // Ensure different ordering returns the same hash.
    {
        DataSpec d1;
        QSet<QString> list1;
        list1 << "one" << "two";
        d1.addStreamData(list1);

        DataSpec d2;
        QSet<QString> list2;
        list2 << "two" << "one";
        d2.addStreamData(list2);
        CPPUNIT_ASSERT(d1.hash() == d2.hash());
    }
}
/**
 * @details
 * Tests two chunkers, starting them multiple times (test for random segfaults
 * and threading problems).
 */
void DirectStreamDataClientTest::test_twoChunkersMultipleStarts()
{
    for (int i = 0; i < 100; ++i) {
        //std::cout << "---------------------------------- " << i << std::endl;
        try {
            // Start two telescope emulators.
            EmulatorDriver emulator1(new RealUdpEmulator(*_emulatorConfig1));
            EmulatorDriver emulator2(new RealUdpEmulator(*_emulatorConfig2));

            // Create the adapter factory.
            AbstractAdapterFactory adapterFactory(_config,
                    "pipeline", "adapters");

            // Create the data client factory.
            DataClientFactory clientFactory(_config, "pipeline",
                    "clients", &adapterFactory);

            // Create the data blob factory.
            FactoryGeneric<DataBlob> blobFactory(true);

            // Create a list of data requirements.
            QString dataType = "DoubleData";
            DataSpec req;
            QList<DataSpec> requirements;
            req.addStreamData(dataType);
            requirements.append(req);

            // Create the client.
            DirectStreamDataClient* client = static_cast<DirectStreamDataClient*>(
                    clientFactory.create("DirectStreamDataClient"));
            CPPUNIT_ASSERT(DataClientFactory::whatIs(client) == "DirectStreamDataClient");
            client->reset( requirements );
            client->addStreamChunker("TestUdpChunker", "a");
            client->addStreamChunker("TestUdpChunker", "b");

            // Set up the data hash.
            QHash<QString, DataBlob*> dataHash;
            dataHash.insert(dataType, blobFactory.create(dataType));

            for (int j = 0; j < 2; j++) {
                // Get the data.
                QHash<QString, DataBlob*> validData = client->getData(dataHash);

                // Check the content of the data blob.
                DoubleData* data = (DoubleData*)validData.value("DoubleData");
                _printData(data);
            }
        }
        catch (QString e) {
            CPPUNIT_FAIL("Unexpected exception: " + e.toStdString());
        }
    }
}
void PelicanServerClientTest::test_getData()
{
    Config config;
    config.setFromString(
            "<testconfig>"
            "   <server host=\"127.0.0.1\"/>"
            "</testconfig>"
            );
    Config::TreeAddress address;
    address << Config::NodeId("testconfig", "");
    ConfigNode configNode = config.get(address);
    TestStreamAdapter streamAdapter;
    QString stream1("stream1");
    QString version1("version1");
    DataSpec req;
    req.addStreamData(stream1);
    {
        // Use Case:
        //    data requirements are set, empty hash passed
        // Expect: throw

        QList<DataSpec> lreq;
        lreq.append(req);
        DataTypes dt;
        dt.setAdapter(stream1,&streamAdapter);
        dt.addData(lreq);
        PelicanServerClient client(configNode, dt, 0);
        QHash<QString, DataBlob*> dataHash;
        CPPUNIT_ASSERT_THROW(client.getData(dataHash), QString );
    }
    {
        // Use Case:
        //    Data Requirements do not match DataBlobs
        // Expect:
        //     throw with a suitable message

        // setup the test
        QList<DataSpec> lreq;
        lreq.append(req);
        DataTypes dt;
        dt.setAdapter(stream1,&streamAdapter);
        dt.addData(lreq);
        PelicanServerClient client(configNode, dt, 0);

        QHash<QString, DataBlob*> dataHash;
        DataBlob db("DataBlob");
        dataHash.insert("pelican/data2", &db);

        CPPUNIT_ASSERT_THROW(client.getData(dataHash), QString);
    }
}
void TCPConnectionManagerTest::test_brokenConnection()
{
    // Use Case:
    // client requests a connection
    // expect client to be registered for any data
    StreamDataRequest req;
    DataSpec require;
    require.addStreamData("testData");
    req.addDataOption(require);

    QTcpSocket* client = _createClient();
    _sendRequest( client, req );
    QCoreApplication::processEvents();

    CPPUNIT_ASSERT_EQUAL( 1, _server->clientsForStream("testData") );

    // Use Case:
    // client dies after connection
    // expect to be removed from the system
    delete client;
    QCoreApplication::processEvents();
    CPPUNIT_ASSERT_EQUAL( 0, _server->clientsForStream("testData") );
}
int main(int argc, char** argv)
{
    try {
    QCoreApplication app(argc, argv);

    // Get command line arguments.
    if (argc != 5) {
        std::cerr << "Usage: directClient <port> <host> <chunk size, bytes> <iterations>" << std::endl;
        return 1;
    }

    int port = atoi(argv[1]);
    QString host(argv[2]);
    int chunkSize = atoi(argv[3]);
    int iterations = atoi(argv[4]);

    QString pipelineXml = ""
            "<buffers>"
            "   <DoubleData>"
            "       <buffer maxSize=\"2000000\" maxChunkSize=\"2000000\"/>"
            "   </DoubleData>"
            "</buffers>"
            "<chunkers>"
            "    <TestUdpChunker name=\"a\">"
            "       <connection host=\"" + host + "\" port=\"" + QString::number(port) + "\"/>"
            "       <data type=\"DoubleData\" chunkSize=\"" + QString::number(chunkSize) + "\"/>"
            "    </TestUdpChunker>"
            "</chunkers>"
            "<clients>"
            "    <DirectStreamDataClient>"
            "        <data type=\"DoubleData\" adapter=\"AdapterRealData\"/>"
            "    </DirectStreamDataClient>"
            "</clients>"
            "<adapters>"
            "</adapters>";
    Config config;
    config.setFromString(pipelineXml);

    // Create the adapter factory.
    AbstractAdapterFactory adapterFactory(&config, "pipeline", "adapters");

    // Create the data client factory.
    DataClientFactory clientFactory(&config, "pipeline", "clients", &adapterFactory);

    // Create the data blob factory.
    //FactoryGeneric<DataBlob> blobFactory;

    // Create a list of data requirements.
    QString dataType = "DoubleData";
    DataSpec req;
    QList<DataSpec> requirements;
    req.addStreamData(dataType);
    requirements.append(req);

    // Create the client.
    DirectStreamDataClient* client = static_cast<DirectStreamDataClient*>(
            clientFactory.create("DirectStreamDataClient"));
    client->reset( requirements );
    client->addStreamChunker("TestUdpChunker", "a");

    // Set up the data hash.
    //QHash<QString, DataBlob*> dataHash;
    //dataHash.insert(dataType, blobFactory.create(dataType));

    // Initialise loop counter.
    QTime timer;
    timer.start();
    int counter = 0;
    double initValue = 0, value = 0;
    for (counter = 0; counter < iterations; counter++) {
        // Get the data.
//        QHash<QString, DataBlob*> validData = client->getData(dataHash);

        // Check the content of the data blob.
//        DoubleData* realData = (DoubleData*)validData.value(dataType);
//        //printData(realData);
//        value = realData->ptr()[0];
//        if (counter == 0)
//            initValue = value;
    }

    // Check for lost packets.
    double dataRange = value - initValue;
    double lostPackets = dataRange + 1 - iterations;

    // Compute bandwidth.
    double sec = (double)timer.elapsed() / 1e3;
    long double megaBytesReceived = (long double)chunkSize * iterations / (1024 * 1024);

    // Print summary.
    std::cout << "---------------------------------------------------------\n";
    std::cout << "Data range " << dataRange << " over " << iterations
            << " iterations. (Missed " << lostPackets << " packets.)\n";
    std::cout << "Received " << megaBytesReceived << " MiB in "
            << sec << " seconds.\n";
    std::cout << "Bandwidth: " << ((megaBytesReceived * 8) / sec)
            << " Mb/sec" << std::endl;
    std::cout << "---------------------------------------------------------\n";

    } catch (QString error) {
        std::cerr << error.toStdString() << std::endl;
    }

    return 0;
}
示例#9
0
void StreamDataRequest::addDataOption(const DataSpec& data)
{
    if( data.streamData().size() != 0 )
        _dataOptions.append(data);
}
示例#10
0
void DataSpecTest::test_isCompatible()
{
    // Use Case:
    // DataSpec matches the data hash
    // expect true
    {
        DataSpec req;
        req.addServiceData("wibble1");
        QHash<QString, DataBlob*> hashData;
        hashData.insert("wibble1", NULL);
        CPPUNIT_ASSERT_EQUAL(true, req.isCompatible(hashData));

        DataSpec reqdata;
        reqdata.addServiceData("wibble1");
        CPPUNIT_ASSERT_EQUAL(true, req.isCompatible(reqdata));
    }

    // Use Case:
    // DataSpec contains a subset of the data hash
    // expect true
    {
        DataSpec req;
        req.addServiceData("wibble1");
        QHash<QString, DataBlob*> hashData;
        hashData.insert("wibble1", NULL);
        hashData.insert("wibble2", NULL);
        CPPUNIT_ASSERT_EQUAL(true, req.isCompatible(hashData));

        DataSpec reqdata;
        reqdata.addServiceData("wibble1");
        reqdata.addServiceData("wibble2");
        CPPUNIT_ASSERT_EQUAL(true, req.isCompatible(reqdata));
    }

    // Use Case:
    // DataSpec contains some elements of the data, but is not compatible with it.
    // The data requirements have an additional data type which is not in the hash.
    // expect false
    {
        DataSpec req;
        QSet<QString> dataTypes;
        dataTypes << "wibble1" << "other";
        req.addServiceData(dataTypes);
        QHash<QString, DataBlob*> hashData;
        hashData.insert("wibble1", NULL);
        hashData.insert("wibble2", NULL);
        CPPUNIT_ASSERT_EQUAL(false, req.isCompatible(hashData));

        DataSpec reqdata;
        reqdata.addServiceData("wibble1");
        reqdata.addServiceData("wibble2");
        CPPUNIT_ASSERT_EQUAL(false, req.isCompatible(reqdata));
    }

}
void PelicanServerClientTest::test_response()
{
    try {
    TestServiceAdapter serviceAdapter;
    TestStreamAdapter streamAdapter;
    ConfigNode configNode;
    configNode.setFromString(
            "<testconfig>"
            "   <server host=\"127.0.0.1\"/>"
            "</testconfig>"
    );
    QString stream1("stream1");
    QString version1("v1");
    QString service1("service1");
    QString serviceVersion1("sv1");
    DataSpec reqStream1;
    reqStream1.addStreamData(stream1);
    QByteArray data1("data1");
    {
        // Use Case
        // receive a StreamData response (single stream, no service data)
        boost::shared_ptr<ServerResponse> res( new StreamDataResponse );
        static_cast<StreamDataResponse*>(res.get())->setStreamData( new StreamData(stream1,version1, data1.size()) );

        // set up the adapters and client
        QList<DataSpec> lreq;
        lreq.append(reqStream1);
        DataTypes dt;
        dt.setAdapter(stream1,&streamAdapter);
        dt.addData(lreq);
        PelicanServerClient client(configNode, dt, 0);

        // set up the memory for receiving data
        TestDataBlob db;
        QHash<QString, DataBlob*> dataHash;
        dataHash.insert(stream1, &db);

        SocketTester st;
        QTcpSocket& sock = st.send(data1);
        QHash<QString, DataBlob*> vhash = client._response( sock , res, dataHash );
        CPPUNIT_ASSERT( vhash == dataHash );
        CPPUNIT_ASSERT_EQUAL( version1.toStdString(), vhash[stream1]->version().toStdString() );
        CPPUNIT_ASSERT_EQUAL( std::string( data1.data() ) , std::string( static_cast<TestDataBlob*>(vhash[stream1])->data() ) );
    }
    QByteArray data2("data2");
    {
        // Use Case
        // ServiceData response - single service data
        boost::shared_ptr<ServerResponse> res( new ServiceDataResponse );
        static_cast<ServiceDataResponse*>(res.get())->addData( new DataChunk(service1,serviceVersion1, data2.size()) );

        // set up the memory for receiving data
        TestDataBlob db;
        QHash<QString, DataBlob*> dataHash;
        dataHash.insert(service1, &db);

        // set up the adapters and client
        DataSpec req;
        req.addStreamData(service1);
        QList<DataSpec> lreq;
        lreq.append(req);
        DataTypes dt;
        dt.setAdapter(service1,&serviceAdapter);
        dt.addData(lreq);
        PelicanServerClient client(configNode, dt, 0);

        SocketTester st;
        QTcpSocket& sock = st.send(data2);
        QHash<QString, DataBlob*> vhash = client._response( sock , res, dataHash );
        CPPUNIT_ASSERT( vhash == dataHash );
        CPPUNIT_ASSERT_EQUAL( serviceVersion1.toStdString(), vhash[service1]->version().toStdString() );
        CPPUNIT_ASSERT_EQUAL( std::string( data2.data() ) , std::string( static_cast<TestDataBlob*>(vhash[service1])->data() ) );
    }
    QString service2("service2");
    {
        // Use Case
        // ServiceData response - multiple service data
        boost::shared_ptr<ServerResponse> res( new ServiceDataResponse );
        static_cast<ServiceDataResponse*>(res.get())->addData( new DataChunk(service1,version1, data1.size()) );
        static_cast<ServiceDataResponse*>(res.get())->addData( new DataChunk(service2,serviceVersion1, data2.size()) );

        // set up the memory for receiving data
        TestDataBlob db;
        TestDataBlob db2;
        QHash<QString, DataBlob*> dataHash;
        dataHash.insert(service1, &db);
        dataHash.insert(service2, &db2);

        // set up the adapters and client
        DataSpec req;
        req.addStreamData(service1);
        QList<DataSpec> lreq;
        lreq.append(req);
        DataTypes dt;
        dt.setAdapter(service1,&serviceAdapter);
        dt.setAdapter(service2,&serviceAdapter);
        dt.addData(lreq);
        PelicanServerClient client(configNode, dt, 0);

        SocketTester st;
        QTcpSocket& sock = st.send( data1 + data2 );
        QHash<QString, DataBlob*> vhash = client._response( sock , res, dataHash );
        CPPUNIT_ASSERT( vhash == dataHash );
        CPPUNIT_ASSERT_EQUAL( version1.toStdString(), vhash[service1]->version().toStdString() );
        CPPUNIT_ASSERT_EQUAL( serviceVersion1.toStdString(), vhash[service2]->version().toStdString() );
        CPPUNIT_ASSERT_EQUAL( std::string( data1.data() ) , std::string( static_cast<TestDataBlob*>(vhash[service1])->data() ) );
        CPPUNIT_ASSERT_EQUAL( std::string( data2.data() ) , std::string( static_cast<TestDataBlob*>(vhash[service2])->data() ) );
    }

//    {
//        // Use Case
//        // receive a StreamData response with associated service data (single stream, single service data)
//        // no existing service data exists
//        boost::shared_ptr<ServerResponse> res( new StreamDataResponse );
//        StreamData* sd = new StreamData(stream1,version1, data1.size());
//        sd->addAssociatedData(boost::shared_ptr<Data>(new Data(service1,serviceVersion1, data2.size()) ) );
//        static_cast<StreamDataResponse*>(res.get())->setStreamData( sd );
//
//        // set up the adapters and client
//        DataSpec req;
//        req.addStreamData(stream1);
//        req.addServiceData(service1);
//        QList<DataSpec> lreq;
//        lreq.append(req);
//        DataTypes dt;
//        dt.setAdapter(stream1,&streamAdapter);
//        dt.setAdapter(service1,&serviceAdapter);
//        dt.addData(lreq);
//        PelicanServerClient client(configNode, dt, 0);
//
//        // set up the memory for receiving data
//        TestDataBlob db;
//        TestDataBlob db2;
//        QHash<QString, DataBlob*> dataHash;
//        dataHash.insert(stream1, &db);
//        dataHash.insert(service1, &db2);
//
//        SocketTester st;
//        QTcpSocket& sock = st.send(data1);
//        try {
//            QHash<QString, DataBlob*> vhash = client._response( sock , res, dataHash );
//        } catch (const QString& e) {
//            CPPUNIT_FAIL(e.toStdString());
//        }
//        CPPUNIT_ASSERT( vhash == dataHash );
//        CPPUNIT_ASSERT_EQUAL( version1.toStdString(), vhash[stream1]->version().toStdString() );
//        CPPUNIT_ASSERT_EQUAL( serviceVersion1.toStdString(), vhash[service1]->version().toStdString() );
//        CPPUNIT_ASSERT_EQUAL( std::string( data1.data() ) , std::string( static_cast<TestDataBlob*>( vhash[stream1])->data() ) );
//        CPPUNIT_ASSERT_EQUAL( std::string( data2.data() ) , std::string( static_cast<TestDataBlob*>( vhash[service1])->data() ) );
//    }

        } catch ( const QString& e ) {
                CPPUNIT_FAIL( e.toStdString() );
        }
}
void FileDataClientTest::test_method()
{
    try {
    Config config;
    config.setFromString(
            "<testconfig>"
            "   <file name=\"testfile.xml\"/>"
            "</testconfig>"
            );
    Config::TreeAddress address;
    address << Config::NodeId("testconfig", "");
    ConfigNode configNode = config.get(address);
/* No longer relevant
    {
        // Use Case:
        //    Empty data requirements
        // Expect: throw with a suitable complaint

        // setup the test
        QList<DataSpec> lreq;
        DataTypes dt;
        dt.addData(lreq);
        FileDataClient* client = 0;
        CPPUNIT_ASSERT_THROW(client = new FileDataClient(configNode, dt, 0), QString);
        delete client;
    }
*/
    TestStreamAdapter streamAdapter;
    QString stream1("stream1");
    QString version1("version1");
    DataSpec req;
    req.addStreamData(stream1);
    {
        // Use Case:
        //    data requirements are set, empty hash passed
        // Expect: throw

        QList<DataSpec> lreq;
        lreq.append(req);
        DataTypes dt;
        dt.setAdapter(stream1,&streamAdapter);
        dt.addData(lreq);
        FileDataClient client(configNode, dt, 0);

        QHash<QString, DataBlob*> dataHash;
        CPPUNIT_ASSERT_THROW(client.getData(dataHash), QString );
    }
    {  // Use Case:
       // Specifiy a single file and associate it with a Stream
       // correct hash is passed
       // Expect:
       // Data in file to be streamed
       DataTypes types;
       types.setAdapter(stream1,&streamAdapter);
       types.addData(req);
       FileDataClient client(configNode, types, &config);

       QHash<QString, DataBlob*> dataHash;
       DataBlob db("DataBlob");
       dataHash.insert(stream1, &db);
       client.getData(dataHash);
    }
    }
    catch( QString& e ) {
        CPPUNIT_FAIL(e.toStdString());
    }
}
示例#13
0
/**
 * @details
 * Test if the DataSpec object is compatible with a hash of data blobs.
 */
bool operator==(const DataSpec& r, const QHash<QString, DataBlob*>& hash)
{
    return r.isCompatible(hash);
}
示例#14
0
/**
 * @details
 * Tests if this requirements object is the same as the other one.
 */
bool DataSpec::operator==(const DataSpec& d) const
{
    return hash() == d.hash();
}