Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mumble-voip/mumble.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThorvald Natvig <slicer@users.sourceforge.net>2007-08-11 18:33:20 +0400
committerThorvald Natvig <slicer@users.sourceforge.net>2007-08-11 18:33:20 +0400
commit36f625a58371623d24dd3cff6d51725ff71a7cd4 (patch)
tree9951797c3d4b3e55c14a8f3a664de071c42699f3
parent467316a9c016cc79e16b7360c6b6cc0bd7695eca (diff)
Start of proper statistics
git-svn-id: https://mumble.svn.sourceforge.net/svnroot/mumble/trunk@723 05730e5d-ab1b-0410-a4ac-84af385074fa
-rw-r--r--src/Connection.cpp12
-rw-r--r--src/Connection.h9
-rw-r--r--src/CryptState.cpp9
-rw-r--r--src/CryptState.h12
-rw-r--r--src/Message.cpp14
-rw-r--r--src/Message.h24
-rw-r--r--src/PacketDataStream.h18
-rw-r--r--src/mumble/MainWindow.cpp33
-rw-r--r--src/mumble/MainWindow.h1
-rw-r--r--src/mumble/Messages.cpp4
-rw-r--r--src/mumble/ServerHandler.cpp46
-rw-r--r--src/mumble/ServerHandler.h4
-rw-r--r--src/murmur/Messages.cpp26
-rw-r--r--src/murmur/Server.h1
-rw-r--r--src/tests/TestPacketDataStream.cpp26
15 files changed, 199 insertions, 40 deletions
diff --git a/src/Connection.cpp b/src/Connection.cpp
index 533f143c1..44d1865df 100644
--- a/src/Connection.cpp
+++ b/src/Connection.cpp
@@ -48,6 +48,11 @@ Connection::Connection(QObject *p, QSslSocket *qtsSock) : QObject(p) {
iPacketLength = -1;
bDisconnectedEmitted = false;
bReentry = false;
+
+ dUDPPingAvg = dUDPPingVar = 0.0L;
+ dTCPPingAvg = dTCPPingVar = 0.0L;
+ uiUDPPackets = uiTCPPackets = 0;
+
connect(qtsSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
connect(qtsSocket, SIGNAL(readyRead()), this, SLOT(socketRead()));
connect(qtsSocket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
@@ -168,6 +173,13 @@ void Connection::disconnectSocket() {
qtsSocket->disconnectFromHost();
}
+void Connection::updatePing(double &avg, double &var, quint32 &samples, quint64 usec) {
+ samples++;
+ double x = usec / 1000.0L;
+ double delta = x - avg;
+ avg += delta / (samples * 1.0L);
+ var += delta * (x - avg);
+};
QHostAddress Connection::peerAddress() const {
return qtsSocket->peerAddress();
diff --git a/src/Connection.h b/src/Connection.h
index abcf8f4f9..40635238e 100644
--- a/src/Connection.h
+++ b/src/Connection.h
@@ -66,6 +66,15 @@ class Connection : public QObject {
CryptState csCrypt;
+ double dUDPPingAvg;
+ double dUDPPingVar;
+ quint32 uiUDPPackets;
+ double dTCPPingAvg;
+ double dTCPPingVar;
+ quint32 uiTCPPackets;
+
+ static void updatePing(double &avg, double &var, quint32 &samples, quint64 usec);
+
QList<QSslCertificate> peerCertificateChain() const;
QSslCipher sessionCipher() const;
QHostAddress peerAddress() const;
diff --git a/src/CryptState.cpp b/src/CryptState.cpp
index 73fbd9176..b3b6bdd42 100644
--- a/src/CryptState.cpp
+++ b/src/CryptState.cpp
@@ -43,7 +43,8 @@ CryptState::CryptState() {
for (int i=0;i<0x100;i++)
decrypt_history[i] = 0;
bInit = false;
- stat_good=stat_late=stat_lost = 0;
+ uiGood=uiLate=uiLost=uiResync=0;
+ uiRemoteGood=uiRemoteLate=uiRemoteLost=uiRemoteResync=0;
}
bool CryptState::isValid() const {
@@ -174,9 +175,9 @@ bool CryptState::decrypt(const unsigned char *source, unsigned char *dst, unsign
if (restore)
memcpy(decrypt_iv, saveiv, AES_BLOCK_SIZE);
- stat_good++;
- stat_late += late;
- stat_lost += lost;
+ uiGood++;
+ uiLate += late;
+ uiLost += lost;
tLastGood.restart();
return true;
diff --git a/src/CryptState.h b/src/CryptState.h
index f804a9325..7ad598576 100644
--- a/src/CryptState.h
+++ b/src/CryptState.h
@@ -41,9 +41,15 @@ class CryptState {
unsigned char decrypt_iv[AES_BLOCK_SIZE];
unsigned char decrypt_history[0x100];
- unsigned int stat_good;
- unsigned int stat_late;
- unsigned int stat_lost;
+ unsigned int uiGood;
+ unsigned int uiLate;
+ unsigned int uiLost;
+ unsigned int uiResync;
+
+ unsigned int uiRemoteGood;
+ unsigned int uiRemoteLate;
+ unsigned int uiRemoteLost;
+ unsigned int uiRemoteResync;
AES_KEY encrypt_key;
AES_KEY decrypt_key;
diff --git a/src/Message.cpp b/src/Message.cpp
index bc0c23960..7162bf2e8 100644
--- a/src/Message.cpp
+++ b/src/Message.cpp
@@ -139,6 +139,9 @@ Message *Message::networkToMessage(PacketDataStream &qdsIn) {
case Ping:
mMsg = new MessagePing();
break;
+ case PingStats:
+ mMsg = new MessagePingStats();
+ break;
case PlayerTexture:
mMsg = new MessageTexture();
break;
@@ -246,6 +249,9 @@ void MessageHandler::dispatch(Connection *cCon, Message *msg) {
case Message::Ping:
msgPing(cCon, static_cast<MessagePing *>(msg));
break;
+ case Message::PingStats:
+ msgPingStats(cCon, static_cast<MessagePingStats *>(msg));
+ break;
case Message::PlayerTexture:
msgTexture(cCon, static_cast<MessageTexture *>(msg));
break;
@@ -278,6 +284,14 @@ void MessagePing::restoreStream(PacketDataStream &qdsIn) {
qdsIn >> uiTimestamp;
}
+void MessagePingStats::saveStream(PacketDataStream &qdsOut) const {
+ qdsOut << uiTimestamp << uiGood << uiLate << uiLost << uiResync << dUDPPingAvg << dUDPPingVar << uiUDPPackets << dTCPPingAvg << dTCPPingVar << uiTCPPackets;
+}
+
+void MessagePingStats::restoreStream(PacketDataStream &qdsIn) {
+ qdsIn >> uiTimestamp >> uiGood >> uiLate >> uiLost >> uiResync >> dUDPPingAvg >> dUDPPingVar >> uiUDPPackets >> dTCPPingAvg >> dTCPPingVar >> uiTCPPackets;
+}
+
MessageServerAuthenticate::MessageServerAuthenticate() {
iVersion = MESSAGE_STREAM_VERSION;
iMaxBandwidth = 100000;
diff --git a/src/Message.h b/src/Message.h
index 87f6e0c01..f618c552e 100644
--- a/src/Message.h
+++ b/src/Message.h
@@ -43,7 +43,7 @@ class Message {
virtual void saveStream(PacketDataStream &) const;
virtual void restoreStream(PacketDataStream &);
public:
- enum MessageType { ServerReject, ServerAuthenticate, Speex, ServerSync, ServerJoin, ServerLeave, ServerBanList, PlayerMute, PlayerDeaf, PlayerKick, PlayerRename, PlayerBan, PlayerMove, PlayerSelfMuteDeaf, ChannelAdd, ChannelRemove, ChannelMove, ChannelLink, ChannelRename, PermissionDenied, EditACL, QueryUsers, Ping, TextMessage, PlayerTexture, CryptSetup, CryptSync };
+ enum MessageType { ServerReject, ServerAuthenticate, Speex, ServerSync, ServerJoin, ServerLeave, ServerBanList, PlayerMute, PlayerDeaf, PlayerKick, PlayerRename, PlayerBan, PlayerMove, PlayerSelfMuteDeaf, ChannelAdd, ChannelRemove, ChannelMove, ChannelLink, ChannelRename, PermissionDenied, EditACL, QueryUsers, Ping, TextMessage, PlayerTexture, CryptSetup, CryptSync, PingStats };
unsigned int uiSession;
Message();
@@ -98,6 +98,27 @@ class MessagePing : public Message {
};
};
+class MessagePingStats : public Message {
+ protected:
+ void saveStream(PacketDataStream &) const;
+ void restoreStream(PacketDataStream &);
+ public:
+ quint64 uiTimestamp;
+ quint32 uiGood;
+ quint32 uiLate;
+ quint32 uiLost;
+ quint32 uiResync;
+ double dUDPPingAvg;
+ double dUDPPingVar;
+ quint32 uiUDPPackets;
+ double dTCPPingAvg;
+ double dTCPPingVar;
+ quint32 uiTCPPackets;
+ Message::MessageType messageType() const {
+ return PingStats;
+ };
+};
+
class MessageServerReject : public Message {
protected:
void saveStream(PacketDataStream &) const;
@@ -418,6 +439,7 @@ class MessageHandler {
virtual void msgSpeex(Connection *, MessageSpeex *) = 0;
virtual void msgServerAuthenticate(Connection *, MessageServerAuthenticate *) = 0;
virtual void msgPing(Connection *, MessagePing *) = 0;
+ virtual void msgPingStats(Connection *, MessagePingStats *) = 0;
virtual void msgServerReject(Connection *, MessageServerReject *) = 0;
virtual void msgServerSync(Connection *, MessageServerSync *) = 0;
virtual void msgServerJoin(Connection *, MessageServerJoin *) = 0;
diff --git a/src/PacketDataStream.h b/src/PacketDataStream.h
index 6ee6ec34e..07ed08e15 100644
--- a/src/PacketDataStream.h
+++ b/src/PacketDataStream.h
@@ -293,6 +293,24 @@ class PacketDataStream {
INTMAPOPERATOR(char);
INTMAPOPERATOR(unsigned char);
+ union double64u {
+ quint64 ui;
+ double d;
+ };
+
+ PacketDataStream &operator <<(const double v) {
+ double64u u;
+ u.d = v;
+ return *this << u.ui;
+ }
+
+ PacketDataStream &operator >>(double &v) {
+ double64u u;
+ *this >> u.ui;
+ v = u.d;
+ return *this;
+ }
+
template <typename T>
PacketDataStream &operator <<(const QList<T> &l) {
*this << l.size();
diff --git a/src/mumble/MainWindow.cpp b/src/mumble/MainWindow.cpp
index 7dbf54769..2f084b1fe 100644
--- a/src/mumble/MainWindow.cpp
+++ b/src/mumble/MainWindow.cpp
@@ -530,23 +530,32 @@ void MainWindow::on_ServerBanList_triggered() {
}
void MainWindow::on_ServerInformation_triggered() {
+ ConnectionPtr c = g.sh->cConnection;
+
+ if (! c)
+ return;
+
+ CryptState &cs = c->csCrypt;
QSslCipher qsc = g.sh->qscCipher;
- QMessageBox qmb(QMessageBox::Information, tr("Mumble Server Information"),
- tr("Control channel: %1 ms latency, Encrypted with %3 bit %4<br />"
- "Voice channel: %2 ms latency, Encrypted with OCB-AES128"
- ).arg(g.sh->uiTCPPing / 1000.0, 0, 'f', 2).arg(g.sh->uiUDPPing / 1000.0, 0, 'f', 2).arg(qsc.usedBits()).arg(qsc.name()), QMessageBox::Ok, this);
- qmb.setDefaultButton(QMessageBox::Ok);
- qmb.setEscapeButton(QMessageBox::Ok);
+ /*FIXME
+ QMessageBox qmb(QMessageBox::Information, tr("Mumble Server Information"),
+ tr("Control channel: %1 ms latency, Encrypted with %3 bit %4<br />"
+ "Voice channel: %2 ms latency, Encrypted with OCB-AES128"
+ ).arg(g.sh->uiTCPPing / 1000.0, 0, 'f', 2).arg(g.sh->uiUDPPing / 1000.0, 0, 'f', 2).arg(qsc.usedBits()).arg(qsc.name()), QMessageBox::Ok, this);
- QPushButton *qp = qmb.addButton(tr("&View Certificate"), QMessageBox::ActionRole);
- int res = qmb.exec();
- if ((res == 0) && (qmb.clickedButton() == qp)) {
- ViewCert vc(g.sh->qscCert, this);
- vc.exec();
- }
+ qmb.setDefaultButton(QMessageBox::Ok);
+ qmb.setEscapeButton(QMessageBox::Ok);
+
+ QPushButton *qp = qmb.addButton(tr("&View Certificate"), QMessageBox::ActionRole);
+ int res = qmb.exec();
+ if ((res == 0) && (qmb.clickedButton() == qp)) {
+ ViewCert vc(g.sh->qscCert, this);
+ vc.exec();
+ }
+ */
}
void MainWindow::on_PlayerMenu_aboutToShow() {
diff --git a/src/mumble/MainWindow.h b/src/mumble/MainWindow.h
index 309514846..26adeb608 100644
--- a/src/mumble/MainWindow.h
+++ b/src/mumble/MainWindow.h
@@ -144,6 +144,7 @@ class MainWindow : public QMainWindow, public MessageHandler {
virtual void msgSpeex(Connection *, MessageSpeex *);
virtual void msgServerAuthenticate(Connection *, MessageServerAuthenticate *);
virtual void msgPing(Connection *, MessagePing *);
+ virtual void msgPingStats(Connection *, MessagePingStats *);
virtual void msgServerReject(Connection *, MessageServerReject *);
virtual void msgServerSync(Connection *, MessageServerSync *);
virtual void msgServerJoin(Connection *, MessageServerJoin *);
diff --git a/src/mumble/Messages.cpp b/src/mumble/Messages.cpp
index 019458a5b..e289b89c8 100644
--- a/src/mumble/Messages.cpp
+++ b/src/mumble/Messages.cpp
@@ -343,6 +343,9 @@ void MainWindow::msgQueryUsers(Connection *, MessageQueryUsers *msg) {
void MainWindow::msgPing(Connection *, MessagePing *) {
}
+void MainWindow::msgPingStats(Connection *, MessagePingStats *) {
+}
+
void MainWindow::msgTexture(Connection *, MessageTexture *msg) {
if (! msg->qbaTexture.isEmpty())
g.o->textureResponse(msg->iPlayerId,msg->qbaTexture);
@@ -363,6 +366,7 @@ void MainWindow::msgCryptSync(Connection *, MessageCryptSync *msg) {
msg->qbaNonce = QByteArray(reinterpret_cast<const char *>(c->csCrypt.encrypt_iv), AES_BLOCK_SIZE);
g.sh->sendMessage(msg);
} else if (msg->qbaNonce.size() == AES_BLOCK_SIZE) {
+ c->csCrypt.uiResync++;
memcpy(c->csCrypt.decrypt_iv, msg->qbaNonce.constData(), AES_BLOCK_SIZE);
}
}
diff --git a/src/mumble/ServerHandler.cpp b/src/mumble/ServerHandler.cpp
index c91180bd5..fb2ee6435 100644
--- a/src/mumble/ServerHandler.cpp
+++ b/src/mumble/ServerHandler.cpp
@@ -48,8 +48,6 @@ ServerHandler::ServerHandler() {
cConnection.reset();
qusUdp = NULL;
- uiTCPPing = uiUDPPing = 0LL;
-
// For some strange reason, on Win32, we have to call supportsSsl before the cipher list is ready.
qWarning("OpenSSL Support: %d", QSslSocket::supportsSsl());
@@ -122,7 +120,7 @@ void ServerHandler::udpReady() {
if (msgType == Message::Ping) {
quint64 t;
pds >> t;
- uiUDPPing = tTimestamp.elapsed() - t;
+ Connection::updatePing(cConnection->dUDPPingAvg, cConnection->dUDPPingVar, cConnection->uiUDPPackets, tTimestamp.elapsed() - t);
} else if (msgType == Message::Speex) {
ClientPlayer *p = ClientPlayer::get(uiSession);
AudioOutputPtr ao = g.ao;
@@ -142,11 +140,11 @@ void ServerHandler::udpReady() {
}
}
-void ServerHandler::sendMessage(Message *mMsg, bool forceTCP) {
+void ServerHandler::sendMessage(Message *mMsg) {
bool mayUdp = (mMsg->messageType() == Message::Speex) || (mMsg->messageType() == Message::Ping);
mMsg->uiSession = g.uiSession;
- if (! forceTCP && mayUdp && ! g.s.bTCPCompat) {
+ if (mayUdp && ! g.s.bTCPCompat) {
QMutexLocker qml(&qmUdp);
if (! qusUdp)
return;
@@ -174,8 +172,6 @@ void ServerHandler::run() {
qlErrors.clear();
qscCert.clear();
- uiUDPPing = uiTCPPing = 0LL;
-
connect(qtsSock, SIGNAL(encrypted()), this, SLOT(serverConnectionConnected()));
connect(cConnection.get(), SIGNAL(connectionClosed(QString)), this, SLOT(serverConnectionClosed(QString)));
connect(cConnection.get(), SIGNAL(message(QByteArray &)), this, SLOT(message(QByteArray &)));
@@ -200,7 +196,6 @@ void ServerHandler::run() {
ticker->stop();
cConnection->disconnectSocket();
cConnection.reset();
-
}
void ServerHandler::setSslErrors(const QList<QSslError> &errors) {
@@ -212,12 +207,24 @@ void ServerHandler::setSslErrors(const QList<QSslError> &errors) {
}
void ServerHandler::sendPing() {
- MessagePing mp;
- mp.uiTimestamp = tTimestamp.elapsed();
-
- sendMessage(&mp, true);
- if (! g.s.bTCPCompat)
- sendMessage(&mp, false);
+ CryptState &cs = cConnection->csCrypt;
+ MessagePingStats mps;
+ mps.uiTimestamp = tTimestamp.elapsed();
+ mps.uiGood = cs.uiGood;
+ mps.uiLate = cs.uiLate;
+ mps.uiLost = cs.uiLost;
+ mps.uiResync = cs.uiResync;
+ mps.dUDPPingAvg = cConnection->dUDPPingAvg;
+ mps.dUDPPingVar = cConnection->dUDPPingVar;
+ mps.dTCPPingAvg = cConnection->dTCPPingAvg;
+ mps.dTCPPingVar = cConnection->dTCPPingVar;
+ sendMessage(&mps);
+
+ if (! g.s.bTCPCompat) {
+ MessagePing mp;
+ mp.uiTimestamp = mps.uiTimestamp;
+ sendMessage(&mp);
+ }
}
void ServerHandler::message(QByteArray &qbaMsg) {
@@ -242,9 +249,14 @@ void ServerHandler::message(QByteArray &qbaMsg) {
ao->removeBuffer(p);
}
}
- } else if (mMsg->messageType() == Message::Ping) {
- MessagePing *mpMsg = static_cast<MessagePing *>(mMsg);
- uiTCPPing = tTimestamp.elapsed() - mpMsg->uiTimestamp;
+ } else if (mMsg->messageType() == Message::PingStats) {
+ MessagePingStats *mpsMsg = static_cast<MessagePingStats *>(mMsg);
+ CryptState &cs = cConnection->csCrypt;
+ cs.uiRemoteGood = mpsMsg->uiGood;
+ cs.uiRemoteLate = mpsMsg->uiLate;
+ cs.uiRemoteLost = mpsMsg->uiLost;
+ cs.uiRemoteResync = mpsMsg->uiResync;
+ Connection::updatePing(cConnection->dTCPPingAvg, cConnection->dTCPPingVar, cConnection->uiTCPPackets, tTimestamp.elapsed() - mpsMsg->uiTimestamp);
} else {
if (mMsg->messageType() == Message::ServerLeave) {
if (ao)
diff --git a/src/mumble/ServerHandler.h b/src/mumble/ServerHandler.h
index aa0e8eb51..9d4737e90 100644
--- a/src/mumble/ServerHandler.h
+++ b/src/mumble/ServerHandler.h
@@ -66,14 +66,12 @@ class ServerHandler : public QThread {
QSslCipher qscCipher;
ConnectionPtr cConnection;
- quint64 uiUDPPing, uiTCPPing;
-
ServerHandler();
~ServerHandler();
void setConnectionInfo(const QString &host, int port, const QString &username, const QString &pw);
void getConnectionInfo(QString &host, int &port, QString &username, QString &pw);
void customEvent(QEvent *evt);
- void sendMessage(Message *m, bool forceTCP=false);
+ void sendMessage(Message *m);
void disconnect();
void run();
signals:
diff --git a/src/murmur/Messages.cpp b/src/murmur/Messages.cpp
index a7c5f64c6..c51048974 100644
--- a/src/murmur/Messages.cpp
+++ b/src/murmur/Messages.cpp
@@ -811,6 +811,31 @@ void Server::msgPing(Connection *cCon, MessagePing *msg) {
sendMessage(cCon, msg);
}
+void Server::msgPingStats(Connection *cCon, MessagePingStats *msg) {
+ MSG_SETUP(Player::Authenticated);
+ CryptState &cs=uSource->csCrypt;
+ cs.uiRemoteGood = msg->uiGood;
+ cs.uiRemoteLate = msg->uiLate;
+ cs.uiRemoteLost = msg->uiLost;
+ cs.uiRemoteResync = msg->uiResync;
+
+ uSource->dUDPPingAvg = msg->dUDPPingAvg;
+ uSource->dUDPPingVar = msg->dUDPPingVar;
+ uSource->uiUDPPackets = msg->uiUDPPackets;
+ uSource->dTCPPingAvg = msg->dTCPPingAvg;
+ uSource->dTCPPingVar = msg->dTCPPingVar;
+ uSource->uiTCPPackets = msg->uiTCPPackets;
+
+ msg->uiGood = cs.uiGood;
+ msg->uiLate = cs.uiLate;
+ msg->uiLost = cs.uiLost;
+ msg->uiResync = cs.uiResync;
+
+ msg->dUDPPingAvg = msg->dUDPPingVar = msg->dTCPPingAvg = msg->dTCPPingVar = 0.0L;
+ msg->uiUDPPackets = msg->uiTCPPackets = 0;
+ sendMessage(cCon, msg);
+}
+
void Server::msgTexture(Connection *cCon, MessageTexture *msg) {
MSG_SETUP(Player::Authenticated);
if (! qhUserTextureCache.contains(msg->iPlayerId)) {
@@ -837,6 +862,7 @@ void Server::msgCryptSync(Connection *cCon, MessageCryptSync *msg) {
msg->qbaNonce = QByteArray(reinterpret_cast<const char *>(uSource->csCrypt.encrypt_iv), AES_BLOCK_SIZE);
sendMessage(cCon, msg);
} else if (msg->qbaNonce.size() == AES_BLOCK_SIZE) {
+ uSource->csCrypt.uiResync++;
memcpy(uSource->csCrypt.decrypt_iv, msg->qbaNonce.constData(), AES_BLOCK_SIZE);
} else {
cCon->disconnectSocket();
diff --git a/src/murmur/Server.h b/src/murmur/Server.h
index 91659876c..d9e6a534b 100644
--- a/src/murmur/Server.h
+++ b/src/murmur/Server.h
@@ -221,6 +221,7 @@ class Server : public QThread, public MessageHandler {
virtual void msgSpeex(Connection *, MessageSpeex *);
virtual void msgServerAuthenticate(Connection *, MessageServerAuthenticate *);
virtual void msgPing(Connection *, MessagePing *);
+ virtual void msgPingStats(Connection *, MessagePingStats *);
virtual void msgServerReject(Connection *, MessageServerReject *);
virtual void msgServerSync(Connection *, MessageServerSync *);
virtual void msgServerJoin(Connection *, MessageServerJoin *);
diff --git a/src/tests/TestPacketDataStream.cpp b/src/tests/TestPacketDataStream.cpp
index 2e72cd90b..7aad73ceb 100644
--- a/src/tests/TestPacketDataStream.cpp
+++ b/src/tests/TestPacketDataStream.cpp
@@ -13,8 +13,34 @@ class TestPacketDataStream : public QObject {
void string();
void string_data();
void space();
+ void floating();
+ void floating_data();
};
+void TestPacketDataStream::floating_data() {
+ QTest::addColumn<double>("value");
+ for (int i=1;i<256;i++) {
+ double v = 1.0L / (1.0L * i);
+ QTest::newRow("Positive") << v;
+ QTest::newRow("Negative") << -v;
+ }
+}
+
+void TestPacketDataStream::floating() {
+ QFETCH(double, value);
+
+ char buff[256];
+ double d;
+
+ PacketDataStream out(buff, 256);
+ out << value;
+ PacketDataStream in(buff, out.size());
+ in >> d;
+ QCOMPARE(value, d);
+ QVERIFY(in.isValid());
+ QVERIFY(in.left() == 0);
+}
+
void TestPacketDataStream::integer_data() {
QTest::addColumn<quint64>("value");
for (int i=0;i<64;i++) {