diff --git a/tests/metavoxels/src/MetavoxelTests.cpp b/tests/metavoxels/src/MetavoxelTests.cpp index dc44134600..48d1d4429d 100644 --- a/tests/metavoxels/src/MetavoxelTests.cpp +++ b/tests/metavoxels/src/MetavoxelTests.cpp @@ -440,6 +440,8 @@ static bool testSerialization(Bitstream::MetadataType metadataType) { } bool MetavoxelTests::run() { + LimitedNodeList::createInstance(); + // seed the random number generator so that our tests are reproducible srand(0xBAAAAABE); @@ -456,14 +458,13 @@ bool MetavoxelTests::run() { } } - QByteArray datagramHeader("testheader"); const int SIMULATION_ITERATIONS = 10000; if (test == 0 || test == 2) { qDebug() << "Running transmission test..."; qDebug(); // create two endpoints with the same header - TestEndpoint alice(datagramHeader), bob(datagramHeader); + TestEndpoint alice, bob; alice.setOther(&bob); bob.setOther(&alice); @@ -497,7 +498,7 @@ bool MetavoxelTests::run() { datagramsReceived = bytesReceived = maxDatagramsPerPacket = maxBytesPerPacket = 0; // create two endpoints with the same header - TestEndpoint alice(datagramHeader, TestEndpoint::CONGESTION_MODE), bob(datagramHeader, TestEndpoint::CONGESTION_MODE); + TestEndpoint alice(TestEndpoint::CONGESTION_MODE), bob(TestEndpoint::CONGESTION_MODE); alice.setOther(&bob); bob.setOther(&alice); @@ -537,8 +538,8 @@ bool MetavoxelTests::run() { datagramsSent = bytesSent = datagramsReceived = bytesReceived = maxDatagramsPerPacket = maxBytesPerPacket = 0; // create client and server endpoints - TestEndpoint client(datagramHeader, TestEndpoint::METAVOXEL_CLIENT_MODE); - TestEndpoint server(datagramHeader, TestEndpoint::METAVOXEL_SERVER_MODE); + TestEndpoint client(TestEndpoint::METAVOXEL_CLIENT_MODE); + TestEndpoint server(TestEndpoint::METAVOXEL_SERVER_MODE); client.setOther(&server); server.setOther(&client); @@ -599,28 +600,57 @@ int RandomVisitor::visit(MetavoxelInfo& info) { return STOP_RECURSION; } -TestEndpoint::TestEndpoint(const QByteArray& datagramHeader, Mode mode) : +class TestSendRecord : public PacketRecord { +public: + + TestSendRecord(const MetavoxelLOD& lod = MetavoxelLOD(), const MetavoxelData& data = MetavoxelData(), + const SharedObjectPointer& localState = SharedObjectPointer(), int packetNumber = 0); + + const SharedObjectPointer& getLocalState() const { return _localState; } + int getPacketNumber() const { return _packetNumber; } + +private: + + SharedObjectPointer _localState; + int _packetNumber; + +}; + +TestSendRecord::TestSendRecord(const MetavoxelLOD& lod, const MetavoxelData& data, + const SharedObjectPointer& localState, int packetNumber) : + PacketRecord(lod, data), + _localState(localState), + _packetNumber(packetNumber) { +} + +class TestReceiveRecord : public PacketRecord { +public: + + TestReceiveRecord(const MetavoxelLOD& lod = MetavoxelLOD(), const MetavoxelData& data = MetavoxelData(), + const SharedObjectPointer& remoteState = SharedObjectPointer()); + + const SharedObjectPointer& getRemoteState() const { return _remoteState; } + +private: + + SharedObjectPointer _remoteState; +}; + +TestReceiveRecord::TestReceiveRecord(const MetavoxelLOD& lod, + const MetavoxelData& data, const SharedObjectPointer& remoteState) : + PacketRecord(lod, data), + _remoteState(remoteState) { +} + +TestEndpoint::TestEndpoint(Mode mode) : + Endpoint(SharedNodePointer(), new TestSendRecord(), new TestReceiveRecord()), _mode(mode), - _sequencer(new DatagramSequencer(datagramHeader, this)), _highPriorityMessagesToSend(0.0f), _reliableMessagesToSend(0.0f) { - connect(_sequencer, SIGNAL(readyToWrite(const QByteArray&)), SLOT(sendDatagram(const QByteArray&))); - connect(_sequencer, SIGNAL(readyToRead(Bitstream&)), SLOT(readMessage(Bitstream&))); - connect(_sequencer, SIGNAL(receivedHighPriorityMessage(const QVariant&)), + connect(&_sequencer, SIGNAL(receivedHighPriorityMessage(const QVariant&)), SLOT(handleHighPriorityMessage(const QVariant&))); - connect(_sequencer, SIGNAL(sendAcknowledged(int)), SLOT(clearSendRecordsBefore(int))); - connect(_sequencer, SIGNAL(receiveAcknowledged(int)), SLOT(clearReceiveRecordsBefore(int))); - - // insert the baseline send record - SendRecord sendRecord = { 0 }; - _sendRecords.append(sendRecord); - - // insert the baseline receive record - ReceiveRecord receiveRecord = { 0 }; - _receiveRecords.append(receiveRecord); - if (mode == METAVOXEL_CLIENT_MODE) { _lod = MetavoxelLOD(glm::vec3(), 0.01f); return; @@ -643,15 +673,15 @@ TestEndpoint::TestEndpoint(const QByteArray& datagramHeader, Mode mode) : // create the object that represents out delta-encoded state _localState = new TestSharedObjectA(); - connect(_sequencer->getReliableInputChannel(), SIGNAL(receivedMessage(const QVariant&)), + connect(_sequencer.getReliableInputChannel(), SIGNAL(receivedMessage(const QVariant&)), SLOT(handleReliableMessage(const QVariant&))); - ReliableChannel* secondInput = _sequencer->getReliableInputChannel(1); + ReliableChannel* secondInput = _sequencer.getReliableInputChannel(1); secondInput->setMessagesEnabled(false); connect(&secondInput->getBuffer(), SIGNAL(readyRead()), SLOT(readReliableChannel())); // enqueue a large amount of data in a low-priority channel - ReliableChannel* output = _sequencer->getReliableOutputChannel(1); + ReliableChannel* output = _sequencer.getReliableOutputChannel(1); output->setPriority(0.25f); output->setMessagesEnabled(false); QByteArray bytes; @@ -804,7 +834,7 @@ bool TestEndpoint::simulate(int iterationNumber) { // update/send our delayed datagrams for (QList::iterator it = _delayedDatagrams.begin(); it != _delayedDatagrams.end(); ) { if (it->second-- == 1) { - _other->receiveDatagram(it->first); + _other->parseData(it->first); it = _delayedDatagrams.erase(it); } else { @@ -819,41 +849,39 @@ bool TestEndpoint::simulate(int iterationNumber) { ByteArrayVector datagrams = _pipeline.takeLast(); _pipeline.prepend(ByteArrayVector()); foreach (const QByteArray& datagram, datagrams) { - _sequencer->receivedDatagram(datagram); + _sequencer.receivedDatagram(datagram); datagramsReceived++; bytesReceived += datagram.size(); _remainingPipelineCapacity += datagram.size(); } - int packetCount = _sequencer->startPacketGroup(); + int packetCount = _sequencer.startPacketGroup(); groupsSent++; maxPacketsPerGroup = qMax(maxPacketsPerGroup, packetCount); for (int i = 0; i < packetCount; i++) { oldDatagramsSent = datagramsSent; oldBytesSent = bytesSent; - Bitstream& out = _sequencer->startPacket(); + Bitstream& out = _sequencer.startPacket(); out << QVariant(); - _sequencer->endPacket(); + _sequencer.endPacket(); maxDatagramsPerPacket = qMax(maxDatagramsPerPacket, datagramsSent - oldDatagramsSent); maxBytesPerPacket = qMax(maxBytesPerPacket, bytesSent - oldBytesSent); // record the send - SendRecord record = { _sequencer->getOutgoingPacketNumber() }; - _sendRecords.append(record); + _sendRecords.append(maybeCreateSendRecord()); } return false; } else if (_mode == METAVOXEL_CLIENT_MODE) { - Bitstream& out = _sequencer->startPacket(); + Bitstream& out = _sequencer.startPacket(); ClientStateMessage state = { _lod }; out << QVariant::fromValue(state); - _sequencer->endPacket(); + _sequencer.endPacket(); // record the send - SendRecord record = { _sequencer->getOutgoingPacketNumber(), SharedObjectPointer(), MetavoxelData(), _lod }; - _sendRecords.append(record); + _sendRecords.append(maybeCreateSendRecord()); } else if (_mode == METAVOXEL_SERVER_MODE) { // make a random change @@ -879,16 +907,15 @@ bool TestEndpoint::simulate(int iterationNumber) { if (!_lod.isValid()) { return false; } - Bitstream& out = _sequencer->startPacket(); + Bitstream& out = _sequencer.startPacket(); out << QVariant::fromValue(MetavoxelDeltaMessage()); - _data.writeDelta(_sendRecords.first().data, _sendRecords.first().lod, out, _lod); - + PacketRecord* sendRecord = getLastAcknowledgedSendRecord(); + _data.writeDelta(sendRecord->getData(), sendRecord->getLOD(), out, _lod); + _sequencer.endPacket(); + // record the send - SendRecord record = { _sequencer->getOutgoingPacketNumber() + 1, SharedObjectPointer(), _data, _lod }; - _sendRecords.append(record); - - _sequencer->endPacket(); - + _sendRecords.append(maybeCreateSendRecord()); + } else { // enqueue some number of high priority messages const float MIN_HIGH_PRIORITY_MESSAGES = 0.0f; @@ -897,7 +924,7 @@ bool TestEndpoint::simulate(int iterationNumber) { while (_highPriorityMessagesToSend >= 1.0f) { QVariant message = createRandomMessage(); _highPriorityMessagesSent.append(message); - _sequencer->sendHighPriorityMessage(message); + _sequencer.sendHighPriorityMessage(message); highPriorityMessagesSent++; _highPriorityMessagesToSend -= 1.0f; } @@ -909,7 +936,7 @@ bool TestEndpoint::simulate(int iterationNumber) { while (_reliableMessagesToSend >= 1.0f) { QVariant message = createRandomMessage(); _reliableMessagesSent.append(message); - _sequencer->getReliableOutputChannel()->sendMessage(message); + _sequencer.getReliableOutputChannel()->sendMessage(message); reliableMessagesSent++; _reliableMessagesToSend -= 1.0f; } @@ -919,12 +946,12 @@ bool TestEndpoint::simulate(int iterationNumber) { // send a packet try { - Bitstream& out = _sequencer->startPacket(); + Bitstream& out = _sequencer.startPacket(); SequencedTestMessage message = { iterationNumber, createRandomMessage(), _localState }; _unreliableMessagesSent.append(message); unreliableMessagesSent++; out << message; - _sequencer->endPacket(); + _sequencer.endPacket(); } catch (const QString& message) { qDebug() << message; @@ -932,14 +959,28 @@ bool TestEndpoint::simulate(int iterationNumber) { } // record the send - SendRecord record = { _sequencer->getOutgoingPacketNumber(), _localState }; - _sendRecords.append(record); + _sendRecords.append(maybeCreateSendRecord()); } maxDatagramsPerPacket = qMax(maxDatagramsPerPacket, datagramsSent - oldDatagramsSent); maxBytesPerPacket = qMax(maxBytesPerPacket, bytesSent - oldBytesSent); return false; } +int TestEndpoint::parseData(const QByteArray& packet) { + if (_mode == CONGESTION_MODE) { + if (packet.size() <= _remainingPipelineCapacity) { + // have to copy the datagram; the one we're passed is a reference to a shared buffer + _pipeline[0].append(QByteArray(packet.constData(), packet.size())); + _remainingPipelineCapacity -= packet.size(); + } + } else { + _sequencer.receivedDatagram(packet); + datagramsReceived++; + bytesReceived += packet.size(); + } + return packet.size(); +} + void TestEndpoint::sendDatagram(const QByteArray& datagram) { datagramsSent++; bytesSent += datagram.size(); @@ -967,21 +1008,7 @@ void TestEndpoint::sendDatagram(const QByteArray& datagram) { } } - _other->receiveDatagram(datagram); -} - -void TestEndpoint::handleHighPriorityMessage(const QVariant& message) { - if (message.userType() == ClearSharedObjectMessage::Type) { - return; - } - if (_other->_highPriorityMessagesSent.isEmpty()) { - throw QString("Received unsent/already sent high priority message."); - } - QVariant sentMessage = _other->_highPriorityMessagesSent.takeFirst(); - if (!messagesEqual(message, sentMessage)) { - throw QString("Sent/received high priority message mismatch."); - } - highPriorityMessagesReceived++; + _other->parseData(datagram); } void TestEndpoint::readMessage(Bitstream& in) { @@ -990,8 +1017,7 @@ void TestEndpoint::readMessage(Bitstream& in) { in >> message; // record the receipt - ReceiveRecord record = { _sequencer->getIncomingPacketNumber() }; - _receiveRecords.append(record); + _receiveRecords.append(maybeCreateReceiveRecord()); return; } if (_mode == METAVOXEL_CLIENT_MODE) { @@ -1000,10 +1026,11 @@ void TestEndpoint::readMessage(Bitstream& in) { handleMessage(message, in); // deep-compare data to sent version - int packetNumber = _sequencer->getIncomingPacketNumber(); - foreach (const SendRecord& sendRecord, _other->_sendRecords) { - if (sendRecord.packetNumber == packetNumber) { - if (!sendRecord.data.deepEquals(_data, _sendRecords.first().lod)) { + int packetNumber = _sequencer.getIncomingPacketNumber(); + foreach (PacketRecord* record, _other->_sendRecords) { + TestSendRecord* sendRecord = static_cast(record); + if (sendRecord->getPacketNumber() == packetNumber) { + if (!sendRecord->getData().deepEquals(_data, getLastAcknowledgedSendRecord()->getLOD())) { qDebug() << "Sent/received metavoxel data mismatch."; exit(true); } @@ -1012,8 +1039,7 @@ void TestEndpoint::readMessage(Bitstream& in) { } // record the receipt - ReceiveRecord record = { packetNumber, SharedObjectPointer(), _data, _sendRecords.first().lod }; - _receiveRecords.append(record); + _receiveRecords.append(maybeCreateReceiveRecord()); return; } if (_mode == METAVOXEL_SERVER_MODE) { @@ -1022,8 +1048,7 @@ void TestEndpoint::readMessage(Bitstream& in) { handleMessage(message, in); // record the receipt - ReceiveRecord record = { _sequencer->getIncomingPacketNumber() }; - _receiveRecords.append(record); + _receiveRecords.append(maybeCreateReceiveRecord()); return; } @@ -1033,8 +1058,7 @@ void TestEndpoint::readMessage(Bitstream& in) { _remoteState = message.state; // record the receipt - ReceiveRecord record = { _sequencer->getIncomingPacketNumber(), message.state }; - _receiveRecords.append(record); + _receiveRecords.append(maybeCreateReceiveRecord()); for (QList::iterator it = _other->_unreliableMessagesSent.begin(); it != _other->_unreliableMessagesSent.end(); it++) { @@ -1056,6 +1080,45 @@ void TestEndpoint::readMessage(Bitstream& in) { exit(true); } +void TestEndpoint::handleMessage(const QVariant& message, Bitstream& in) { + int userType = message.userType(); + if (userType == ClientStateMessage::Type) { + ClientStateMessage state = message.value(); + _lod = state.lod; + + } else if (userType == MetavoxelDeltaMessage::Type) { + PacketRecord* receiveRecord = getLastAcknowledgedReceiveRecord(); + _data.readDelta(receiveRecord->getData(), receiveRecord->getLOD(), in, getLastAcknowledgedSendRecord()->getLOD()); + + } else if (userType == QMetaType::QVariantList) { + foreach (const QVariant& element, message.toList()) { + handleMessage(element, in); + } + } +} + +PacketRecord* TestEndpoint::maybeCreateSendRecord() const { + return new TestSendRecord(_lod, _data, _localState, _sequencer.getOutgoingPacketNumber()); +} + +PacketRecord* TestEndpoint::maybeCreateReceiveRecord() const { + return new TestReceiveRecord(getLastAcknowledgedSendRecord()->getLOD(), _data, _remoteState); +} + +void TestEndpoint::handleHighPriorityMessage(const QVariant& message) { + if (message.userType() == ClearSharedObjectMessage::Type) { + return; + } + if (_other->_highPriorityMessagesSent.isEmpty()) { + throw QString("Received unsent/already sent high priority message."); + } + QVariant sentMessage = _other->_highPriorityMessagesSent.takeFirst(); + if (!messagesEqual(message, sentMessage)) { + throw QString("Sent/received high priority message mismatch."); + } + highPriorityMessagesReceived++; +} + void TestEndpoint::handleReliableMessage(const QVariant& message) { if (message.userType() == ClearSharedObjectMessage::Type || message.userType() == ClearMainChannelSharedObjectMessage::Type) { @@ -1072,7 +1135,7 @@ void TestEndpoint::handleReliableMessage(const QVariant& message) { } void TestEndpoint::readReliableChannel() { - CircularBuffer& buffer = _sequencer->getReliableInputChannel(1)->getBuffer(); + CircularBuffer& buffer = _sequencer.getReliableInputChannel(1)->getBuffer(); QByteArray bytes = buffer.read(buffer.bytesAvailable()); if (_other->_dataStreamed.size() < bytes.size()) { throw QString("Received unsent/already sent streamed data."); @@ -1085,44 +1148,6 @@ void TestEndpoint::readReliableChannel() { streamedBytesReceived += bytes.size(); } -void TestEndpoint::clearSendRecordsBefore(int index) { - _sendRecords.erase(_sendRecords.begin(), _sendRecords.begin() + index + 1); -} - -void TestEndpoint::clearReceiveRecordsBefore(int index) { - _receiveRecords.erase(_receiveRecords.begin(), _receiveRecords.begin() + index + 1); -} - -void TestEndpoint::receiveDatagram(const QByteArray& datagram) { - if (_mode == CONGESTION_MODE) { - if (datagram.size() <= _remainingPipelineCapacity) { - // have to copy the datagram; the one we're passed is a reference to a shared buffer - _pipeline[0].append(QByteArray(datagram.constData(), datagram.size())); - _remainingPipelineCapacity -= datagram.size(); - } - } else { - _sequencer->receivedDatagram(datagram); - datagramsReceived++; - bytesReceived += datagram.size(); - } -} - -void TestEndpoint::handleMessage(const QVariant& message, Bitstream& in) { - int userType = message.userType(); - if (userType == ClientStateMessage::Type) { - ClientStateMessage state = message.value(); - _lod = state.lod; - - } else if (userType == MetavoxelDeltaMessage::Type) { - _data.readDelta(_receiveRecords.first().data, _receiveRecords.first().lod, in, _sendRecords.first().lod); - - } else if (userType == QMetaType::QVariantList) { - foreach (const QVariant& element, message.toList()) { - handleMessage(element, in); - } - } -} - TestSharedObjectA::TestSharedObjectA(float foo, TestEnum baz, TestFlags bong) : _foo(foo), _baz(baz), diff --git a/tests/metavoxels/src/MetavoxelTests.h b/tests/metavoxels/src/MetavoxelTests.h index 96d719a875..476a8c6295 100644 --- a/tests/metavoxels/src/MetavoxelTests.h +++ b/tests/metavoxels/src/MetavoxelTests.h @@ -15,8 +15,7 @@ #include #include -#include -#include +#include #include class SequencedTestMessage; @@ -35,14 +34,14 @@ public: }; /// Represents a simulated endpoint. -class TestEndpoint : public QObject { +class TestEndpoint : public Endpoint { Q_OBJECT public: enum Mode { BASIC_PEER_MODE, CONGESTION_MODE, METAVOXEL_SERVER_MODE, METAVOXEL_CLIENT_MODE }; - TestEndpoint(const QByteArray& datagramHeader, Mode mode = BASIC_PEER_MODE); + TestEndpoint(Mode mode = BASIC_PEER_MODE); void setOther(TestEndpoint* other) { _other = other; } @@ -50,45 +49,28 @@ public: /// \return true if failure was detected bool simulate(int iterationNumber); -private slots: + virtual int parseData(const QByteArray& packet); + +protected: - void sendDatagram(const QByteArray& datagram); + virtual void sendDatagram(const QByteArray& data); + virtual void readMessage(Bitstream& in); + + virtual void handleMessage(const QVariant& message, Bitstream& in); + + virtual PacketRecord* maybeCreateSendRecord() const; + virtual PacketRecord* maybeCreateReceiveRecord() const; + +private slots: + void handleHighPriorityMessage(const QVariant& message); - void readMessage(Bitstream& in); void handleReliableMessage(const QVariant& message); void readReliableChannel(); - void clearSendRecordsBefore(int index); - void clearReceiveRecordsBefore(int index); - private: - void receiveDatagram(const QByteArray& datagram); - - void handleMessage(const QVariant& message, Bitstream& in); - - class SendRecord { - public: - int packetNumber; - SharedObjectPointer localState; - MetavoxelData data; - MetavoxelLOD lod; - }; - - class ReceiveRecord { - public: - int packetNumber; - SharedObjectPointer remoteState; - MetavoxelData data; - MetavoxelLOD lod; - }; - Mode _mode; - DatagramSequencer* _sequencer; - QList _sendRecords; - QList _receiveRecords; - SharedObjectPointer _localState; SharedObjectPointer _remoteState;