summaryrefslogtreecommitdiff
path: root/Plugins/jingle/libjingle/talk/base/virtualsocket_unittest.cc
diff options
context:
space:
mode:
authorpescuma <pescuma@c086bb3d-8645-0410-b8da-73a8550f86e7>2011-10-10 01:39:18 +0000
committerpescuma <pescuma@c086bb3d-8645-0410-b8da-73a8550f86e7>2011-10-10 01:39:18 +0000
commite9bf8a6e2d782dc480fb97cb59928c8cfe1dd777 (patch)
tree12bb8ebaab13ef1476ce9343482796c901ee0130 /Plugins/jingle/libjingle/talk/base/virtualsocket_unittest.cc
parentf574681d9b6fee0d05319af1831620e48cc8492f (diff)
Moved files from BerliOS
git-svn-id: http://pescuma.googlecode.com/svn/trunk/Miranda@229 c086bb3d-8645-0410-b8da-73a8550f86e7
Diffstat (limited to 'Plugins/jingle/libjingle/talk/base/virtualsocket_unittest.cc')
-rw-r--r--Plugins/jingle/libjingle/talk/base/virtualsocket_unittest.cc239
1 files changed, 239 insertions, 0 deletions
diff --git a/Plugins/jingle/libjingle/talk/base/virtualsocket_unittest.cc b/Plugins/jingle/libjingle/talk/base/virtualsocket_unittest.cc
new file mode 100644
index 0000000..16456a2
--- /dev/null
+++ b/Plugins/jingle/libjingle/talk/base/virtualsocket_unittest.cc
@@ -0,0 +1,239 @@
+// Copyright 2006, Google Inc.
+
+#include <complex>
+#include <iostream>
+#include <cassert>
+
+#include "talk/base/thread.h"
+#include "talk/base/virtualsocketserver.h"
+#include "talk/base/testclient.h"
+#include "talk/base/time.h"
+
+#ifdef POSIX
+extern "C" {
+#include <errno.h>
+}
+#endif // POSIX
+
+using namespace talk_base;
+
+void test_basic(Thread* thread, VirtualSocketServer* ss) {
+ std::cout << "basic: ";
+ std::cout.flush();
+
+ SocketAddress addr1(ss->GetNextIP(), 5000);
+ AsyncUDPSocket* socket = CreateAsyncUDPSocket(ss);
+ socket->Bind(addr1);
+
+ TestClient* client1 = new TestClient(socket);
+ TestClient* client2 = new TestClient(CreateAsyncUDPSocket(ss));
+
+ SocketAddress addr2;
+ client2->SendTo("foo", 3, addr1);
+ client1->CheckNextPacket("foo", 3, &addr2);
+
+ SocketAddress addr3;
+ client1->SendTo("bizbaz", 6, addr2);
+ client2->CheckNextPacket("bizbaz", 6, &addr3);
+ assert(addr3 == addr1);
+
+ for (int i = 0; i < 10; i++) {
+ client2 = new TestClient(CreateAsyncUDPSocket(ss));
+
+ SocketAddress addr4;
+ client2->SendTo("foo", 3, addr1);
+ client1->CheckNextPacket("foo", 3, &addr4);
+ assert((addr4.ip() == addr2.ip()) && (addr4.port() == addr2.port() + 1));
+
+ SocketAddress addr5;
+ client1->SendTo("bizbaz", 6, addr4);
+ client2->CheckNextPacket("bizbaz", 6, &addr5);
+ assert(addr5 == addr1);
+
+ addr2 = addr4;
+ }
+
+ std::cout << "PASS" << std::endl;
+}
+
+// Sends at a constant rate but with random packet sizes.
+struct Sender : public MessageHandler {
+ Sender(Thread* th, AsyncUDPSocket* s, uint32 rt)
+ : thread(th), socket(s), done(false), rate(rt), count(0) {
+ last_send = GetMillisecondCount();
+ thread->PostDelayed(NextDelay(), this, 1);
+ }
+
+ uint32 NextDelay() {
+ uint32 size = (rand() % 4096) + 1;
+ return 1000 * size / rate;
+ }
+
+ void OnMessage(Message* pmsg) {
+ assert(pmsg->message_id == 1);
+
+ if (done)
+ return;
+
+ uint32 cur_time = GetMillisecondCount();
+ uint32 delay = cur_time - last_send;
+ uint32 size = rate * delay / 1000;
+ size = std::min(size, uint32(4096));
+ size = std::max(size, uint32(4));
+
+ count += size;
+ *reinterpret_cast<uint32*>(dummy) = cur_time;
+ socket->Send(dummy, size);
+
+ last_send = cur_time;
+ thread->PostDelayed(NextDelay(), this, 1);
+ }
+
+ Thread* thread;
+ AsyncUDPSocket* socket;
+ bool done;
+ uint32 rate; // bytes per second
+ uint32 count;
+ uint32 last_send;
+ char dummy[4096];
+};
+
+struct Receiver : public MessageHandler, public sigslot::has_slots<> {
+ Receiver(Thread* th, AsyncUDPSocket* s, uint32 bw)
+ : thread(th), socket(s), bandwidth(bw), done(false), count(0),
+ sec_count(0), sum(0), sum_sq(0), samples(0) {
+ socket->SignalReadPacket.connect(this, &Receiver::OnReadPacket);
+ thread->PostDelayed(1000, this, 1);
+ }
+
+ ~Receiver() {
+ thread->Clear(this);
+ }
+
+ void OnReadPacket(
+ const char* data, size_t size, const SocketAddress& remote_addr,
+ AsyncPacketSocket* s) {
+ assert(s == socket);
+ assert(size >= 4);
+
+ count += size;
+ sec_count += size;
+
+ uint32 send_time = *reinterpret_cast<const uint32*>(data);
+ uint32 recv_time = GetMillisecondCount();
+ uint32 delay = recv_time - send_time;
+ sum += delay;
+ sum_sq += delay * delay;
+ samples += 1;
+ }
+
+ void OnMessage(Message* pmsg) {
+ assert(pmsg->message_id == 1);
+ // It is always possible for us to receive more than expected because
+ // packets can be further delayed in delivery.
+ if (bandwidth > 0)
+ assert(sec_count <= 5 * bandwidth / 4);
+ sec_count = 0;
+ thread->PostDelayed(1000, this, 1);
+ }
+
+ Thread* thread;
+ AsyncUDPSocket* socket;
+ uint32 bandwidth;
+ bool done;
+ uint32 count;
+ uint32 sec_count;
+ double sum;
+ double sum_sq;
+ uint32 samples;
+};
+
+void test_bandwidth(Thread* thread, VirtualSocketServer* ss) {
+ std::cout << "bandwidth: ";
+ std::cout.flush();
+
+ AsyncUDPSocket* send_socket = CreateAsyncUDPSocket(ss);
+ AsyncUDPSocket* recv_socket = CreateAsyncUDPSocket(ss);
+ assert(send_socket->Bind(SocketAddress(ss->GetNextIP(), 1000)) >= 0);
+ assert(recv_socket->Bind(SocketAddress(ss->GetNextIP(), 1000)) >= 0);
+ assert(send_socket->Connect(recv_socket->GetLocalAddress()) >= 0);
+
+ uint32 bandwidth = 64 * 1024;
+ ss->set_bandwidth(bandwidth);
+
+ Sender sender(thread, send_socket, 80 * 1024);
+ Receiver receiver(thread, recv_socket, bandwidth);
+
+ Thread* pthMain = Thread::Current();
+ pthMain->ProcessMessages(5000);
+ sender.done = true;
+ pthMain->ProcessMessages(5000);
+
+ assert(receiver.count >= 5 * 3 * bandwidth / 4);
+ assert(receiver.count <= 6 * bandwidth); // queue could drain for 1 sec
+
+ delete send_socket;
+ delete recv_socket;
+
+ ss->set_bandwidth(0);
+
+ std::cout << "PASS" << std::endl;
+}
+
+void test_delay(Thread* thread, VirtualSocketServer* ss) {
+ std::cout << "delay: ";
+ std::cout.flush();
+
+ uint32 mean = 2000;
+ uint32 stddev = 500;
+
+ ss->set_delay_mean(mean);
+ ss->set_delay_stddev(stddev);
+ ss->UpdateDelayDistribution();
+
+ AsyncUDPSocket* send_socket = CreateAsyncUDPSocket(ss);
+ AsyncUDPSocket* recv_socket = CreateAsyncUDPSocket(ss);
+ assert(send_socket->Bind(SocketAddress(ss->GetNextIP(), 1000)) >= 0);
+ assert(recv_socket->Bind(SocketAddress(ss->GetNextIP(), 1000)) >= 0);
+ assert(send_socket->Connect(recv_socket->GetLocalAddress()) >= 0);
+
+ Sender sender(thread, send_socket, 64 * 1024);
+ Receiver receiver(thread, recv_socket, 0);
+
+ Thread* pthMain = Thread::Current();
+ pthMain->ProcessMessages(5000);
+ sender.done = true;
+ pthMain->ProcessMessages(5000);
+
+ double sample_mean = receiver.sum / receiver.samples;
+ double num = receiver.sum_sq - 2 * sample_mean * receiver.sum +
+ receiver.samples * sample_mean * sample_mean;
+ double sample_stddev = std::sqrt(num / (receiver.samples - 1));
+std::cout << "mean=" << sample_mean << " dev=" << sample_stddev << std::endl;
+
+ assert(0.9 * mean <= sample_mean);
+ assert(sample_mean <= 1.1 * mean);
+ assert(0.9 * stddev <= sample_stddev);
+ assert(sample_stddev <= 1.1 * stddev);
+
+ delete send_socket;
+ delete recv_socket;
+
+ ss->set_delay_mean(0);
+ ss->set_delay_stddev(0);
+ ss->UpdateDelayDistribution();
+
+ std::cout << "PASS" << std::endl;
+}
+
+int main(int argc, char* argv) {
+ Thread *pthMain = Thread::Current();
+ VirtualSocketServer* ss = new VirtualSocketServer();
+ pthMain->set_socketserver(ss);
+
+ test_basic(pthMain, ss);
+ test_bandwidth(pthMain, ss);
+ test_delay(pthMain, ss);
+
+ return 0;
+}