From 41f78bb85ed895e9f0791905e1871adc260296ac Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Wed, 30 Sep 2009 18:44:35 +0200 Subject: [PATCH] bug 675: convert unit tests to new test framework --- src/internet-stack/tcp-test.cc | 492 +++++++++++++++------------------ 1 file changed, 226 insertions(+), 266 deletions(-) diff --git a/src/internet-stack/tcp-test.cc b/src/internet-stack/tcp-test.cc index 870fe050b..140bf0199 100644 --- a/src/internet-stack/tcp-test.cc +++ b/src/internet-stack/tcp-test.cc @@ -1,6 +1,7 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2007 Georgia Tech Research Corporation + * Copyright (c) 2009 INRIA * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -15,13 +16,9 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Author: Raj Bhattacharjea + * Authors: Mathieu Lacage + * Raj Bhattacharjea */ -/** - * This is the test code for tcp-socket-impl.cc, it was moved out of tcp-socket-impl.cc - * to be in an independent file for clarity purposes. - */ -#ifdef RUN_SELF_TESTS #include "ns3/test.h" #include "ns3/socket-factory.h" @@ -47,10 +44,200 @@ #include namespace ns3 { - -static void -AddInternetStack (Ptr node) + +class TcpTestCase : public TestCase { +public: + TcpTestCase (uint32_t totalStreamSize, + uint32_t sourceWriteSize, + uint32_t sourceReadSize, + uint32_t serverWriteSize, + uint32_t serverReadSize); +private: + virtual bool DoRun (void); + virtual void DoTeardown (void); + void SetupDefaultSim (void); + + Ptr CreateInternetNode (void); + Ptr AddSimpleNetDevice (Ptr node, const char* ipaddr, const char* netmask); + void ServerHandleConnectionCreated (Ptr s, const Address & addr); + void ServerHandleRecv (Ptr sock); + void ServerHandleSend (Ptr sock, uint32_t available); + void SourceHandleSend (Ptr sock, uint32_t available); + void SourceHandleRecv (Ptr sock); + + uint32_t m_totalBytes; + uint32_t m_sourceWriteSize; + uint32_t m_sourceReadSize; + uint32_t m_serverWriteSize; + uint32_t m_serverReadSize; + uint32_t m_currentSourceTxBytes; + uint32_t m_currentSourceRxBytes; + uint32_t m_currentServerRxBytes; + uint32_t m_currentServerTxBytes; + uint8_t *m_sourceTxPayload; + uint8_t *m_sourceRxPayload; + uint8_t* m_serverRxPayload; +}; + +static std::string Name (std::string str, uint32_t totalStreamSize, + uint32_t sourceWriteSize, + uint32_t serverReadSize, + uint32_t serverWriteSize, + uint32_t sourceReadSize) +{ + std::ostringstream oss; + oss << str << " total=" << totalStreamSize << " sourceWrite=" << sourceWriteSize + << " sourceRead=" << sourceReadSize << " serverRead=" << serverReadSize + << " serverWrite=" << serverWriteSize; + return oss.str (); +} + +TcpTestCase::TcpTestCase (uint32_t totalStreamSize, + uint32_t sourceWriteSize, + uint32_t sourceReadSize, + uint32_t serverWriteSize, + uint32_t serverReadSize) + : TestCase (Name ("Send string data from client to server and back", + totalStreamSize, + sourceWriteSize, + serverReadSize, + serverWriteSize, + sourceReadSize)), + m_totalBytes (totalStreamSize), + m_sourceWriteSize (sourceWriteSize), + m_sourceReadSize (sourceReadSize), + m_serverWriteSize (serverWriteSize), + m_serverReadSize (serverReadSize) +{} + +bool +TcpTestCase::DoRun (void) +{ + m_currentSourceTxBytes = 0; + m_currentSourceRxBytes = 0; + m_currentServerRxBytes = 0; + m_currentServerTxBytes = 0; + m_sourceTxPayload = new uint8_t [m_totalBytes]; + m_sourceRxPayload = new uint8_t [m_totalBytes]; + m_serverRxPayload = new uint8_t [m_totalBytes]; + for(uint32_t i = 0; i < m_totalBytes; ++i) + { + uint8_t m = (uint8_t)(97 + (i % 26)); + m_sourceTxPayload[i] = m; + } + memset (m_sourceRxPayload, 0, m_totalBytes); + memset (m_serverRxPayload, 0, m_totalBytes); + + SetupDefaultSim (); + + Simulator::Run (); + + NS_TEST_EXPECT_MSG_EQ (m_currentSourceTxBytes, m_totalBytes, "Source sent all bytes"); + NS_TEST_EXPECT_MSG_EQ (m_currentServerRxBytes, m_totalBytes, "Server received all bytes"); + NS_TEST_EXPECT_MSG_EQ (m_currentSourceRxBytes, m_totalBytes, "Source received all bytes"); + NS_TEST_EXPECT_MSG_EQ (memcmp (m_sourceTxPayload, m_serverRxPayload, m_totalBytes), 0, + "Server received expected data buffers"); + NS_TEST_EXPECT_MSG_EQ (memcmp (m_sourceTxPayload, m_sourceRxPayload, m_totalBytes), 0, + "Source received back expected data buffers"); + + return false; +} +void +TcpTestCase::DoTeardown (void) +{ + delete [] m_sourceTxPayload; + delete [] m_sourceRxPayload; + delete [] m_serverRxPayload; + Simulator::Destroy (); +} + +void +TcpTestCase::ServerHandleConnectionCreated (Ptr s, const Address & addr) +{ + s->SetRecvCallback (MakeCallback (&TcpTestCase::ServerHandleRecv, this)); + s->SetSendCallback (MakeCallback (&TcpTestCase::ServerHandleSend, this)); +} + +void +TcpTestCase::ServerHandleRecv (Ptr sock) +{ + while (sock->GetRxAvailable () > 0) + { + uint32_t toRead = std::min (m_serverReadSize, sock->GetRxAvailable ()); + Ptr p = sock->Recv (toRead, 0); + if (p == 0 && sock->GetErrno () != Socket::ERROR_NOTERROR) + { + NS_FATAL_ERROR ("Server could not read stream at byte " << m_currentServerRxBytes); + } + NS_TEST_EXPECT_MSG_EQ ((m_currentServerRxBytes + p->GetSize () <= m_totalBytes), true, + "Server received too many bytes"); + p->CopyData (&m_serverRxPayload[m_currentServerRxBytes], p->GetSize ()); + m_currentServerRxBytes += p->GetSize (); + ServerHandleSend (sock, sock->GetTxAvailable ()); + } +} + +void +TcpTestCase::ServerHandleSend (Ptr sock, uint32_t available) +{ + while (sock->GetTxAvailable () > 0 && m_currentServerTxBytes < m_currentServerRxBytes) + { + uint32_t left = m_currentServerRxBytes - m_currentServerTxBytes; + uint32_t toSend = std::min (left, sock->GetTxAvailable ()); + toSend = std::min (toSend, m_serverWriteSize); + Ptr p = Create (&m_serverRxPayload[m_currentServerTxBytes], toSend); + int sent = sock->Send (p); + NS_TEST_EXPECT_MSG_EQ ((sent != -1), true, "Server error during send ?"); + m_currentServerTxBytes += sent; + } + if (m_currentServerTxBytes == m_totalBytes) + { + sock->Close (); + } +} + +void +TcpTestCase::SourceHandleSend (Ptr sock, uint32_t available) +{ + while (sock->GetTxAvailable () > 0 && m_currentSourceTxBytes < m_totalBytes) + { + uint32_t left = m_totalBytes - m_currentSourceTxBytes; + uint32_t toSend = std::min (left, sock->GetTxAvailable ()); + toSend = std::min (toSend, m_sourceWriteSize); + Ptr p = Create (&m_sourceTxPayload[m_currentSourceTxBytes], toSend); + int sent = sock->Send (p); + NS_TEST_EXPECT_MSG_EQ ((sent != -1), true, "Error during send ?"); + m_currentSourceTxBytes += sent; + } +} + +void +TcpTestCase::SourceHandleRecv (Ptr sock) +{ + while (sock->GetRxAvailable () > 0 && m_currentSourceRxBytes < m_totalBytes) + { + uint32_t toRead = std::min (m_sourceReadSize, sock->GetRxAvailable ()); + Ptr p = sock->Recv (toRead, 0); + if (p == 0 && sock->GetErrno () != Socket::ERROR_NOTERROR) + { + NS_FATAL_ERROR ("Source could not read stream at byte " << m_currentSourceRxBytes); + } + NS_TEST_EXPECT_MSG_EQ ((m_currentSourceRxBytes + p->GetSize () <= m_totalBytes), true, + "Source received too many bytes"); + p->CopyData (&m_sourceRxPayload[m_currentSourceRxBytes], p->GetSize ()); + m_currentSourceRxBytes += p->GetSize (); + } + if (m_currentSourceRxBytes == m_totalBytes) + { + sock->Close (); + } +} + +Ptr +TcpTestCase::CreateInternetNode () +{ + Ptr node = CreateObject (); //ARP Ptr arp = CreateObject (); node->AggregateObject(arp); @@ -71,234 +258,11 @@ AddInternetStack (Ptr node) //TCP Ptr tcp = CreateObject (); node->AggregateObject(tcp); -} - -class TcpSocketImplTest: public Test -{ - public: - TcpSocketImplTest (); - virtual bool RunTests (void); - private: - //test 1, which sends string "Hello world" server->client - void Test1 (void); - void Test1_HandleConnectionCreated (Ptr, const Address &); - void Test1_HandleRecv (Ptr sock); - - //test 2, which sends a number of bytes server->client - void Test2 (uint32_t payloadSize); - void Test2_HandleConnectionCreated (Ptr, const Address &); - void Test2_HandleRecv (Ptr sock); - uint32_t test2_payloadSize; - - //test 3, which makes sure the rx buffer is finite - void Test3 (uint32_t payloadSize); - void Test3_HandleConnectionCreated (Ptr, const Address &); - void Test3_HandleRecv (Ptr sock); - uint32_t test3_payloadSize; - - //helpers to make topology construction easier - Ptr CreateInternetNode (); - Ptr AddSimpleNetDevice (Ptr,const char*,const char*); - void SetupDefaultSim (); - - //reset all of the below state for another run - void Reset (); - - //all of the state this class needs; basically both ends of the connection, - //and this test kind of acts as an single application running on both nodes - //simultaneously - Ptr node0; - Ptr node1; - Ptr dev0; - Ptr dev1; - Ptr channel; - Ptr listeningSock; - Ptr sock0; - Ptr sock1; - uint32_t rxBytes0; - uint32_t rxBytes1; - - uint8_t* rxPayload; - - bool result; -}; - -TcpSocketImplTest::TcpSocketImplTest () - : Test ("TcpSocketImpl"), - rxBytes0 (0), - rxBytes1 (0), - rxPayload (0), - result (true) -{ -} - -bool -TcpSocketImplTest::RunTests (void) -{ - Test1(); - if (!result) return false; - Test2(600); - if (!result) return false; - Test3(20000); - return result; -} - -//----------------------------------------------------------------------------- -//test 1----------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void -TcpSocketImplTest::Test1 () -{ - SetupDefaultSim (); - listeningSock->SetAcceptCallback - (MakeNullCallback, const Address &> (), - MakeCallback(&TcpSocketImplTest::Test1_HandleConnectionCreated,this)); - sock1->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test1_HandleRecv, this)); - - Simulator::Run (); - Simulator::Destroy (); - - result = result && (rxBytes1 == 13); - result = result && (strcmp((const char*) rxPayload,"Hello World!") == 0); - - Reset (); -} - -void -TcpSocketImplTest::Test1_HandleConnectionCreated (Ptr s, const Address & addr) -{ - NS_ASSERT(s != listeningSock); - NS_ASSERT(sock0 == 0); - sock0 = s; - const uint8_t* hello = (uint8_t*)"Hello World!"; - Ptr p = Create (hello, 13); - sock0->Send(p); - - sock0->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test1_HandleRecv, this)); -} - -void -TcpSocketImplTest::Test1_HandleRecv (Ptr sock) -{ - NS_ASSERT (sock == sock0 || sock == sock1); - Ptr p = sock->Recv(); - uint32_t sz = p->GetSize(); - if (sock == sock1) - { - rxBytes1 += sz; - rxPayload = new uint8_t[sz]; - p->CopyData (rxPayload, sz); - } - else - { - NS_FATAL_ERROR ("Recv from unknown socket "<SetAcceptCallback - (MakeNullCallback, const Address &> (), - MakeCallback(&TcpSocketImplTest::Test2_HandleConnectionCreated,this)); - sock1->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test2_HandleRecv, this)); - - Simulator::Run (); - Simulator::Destroy (); - - result = result && (rxBytes1 == test2_payloadSize); - - Reset (); -} - -void -TcpSocketImplTest::Test2_HandleConnectionCreated (Ptr s, const Address & addr) -{ - NS_ASSERT(s != listeningSock); - NS_ASSERT(sock0 == 0); - sock0 = s; - Ptr p = Create (test2_payloadSize); - sock0->Send(p); - - sock0->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test2_HandleRecv, this)); -} - -void -TcpSocketImplTest::Test2_HandleRecv (Ptr sock) -{ - NS_ASSERT (sock == sock0 || sock == sock1); - Ptr p = sock->Recv(); - uint32_t sz = p->GetSize(); - if (sock == sock1) - { - rxBytes1 += sz; - } - else - { - NS_FATAL_ERROR ("Not supposed to be back traffic in test 2..."<SetAcceptCallback - (MakeNullCallback, const Address &> (), - MakeCallback(&TcpSocketImplTest::Test3_HandleConnectionCreated,this)); - sock1->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test3_HandleRecv, this)); - - Simulator::Run (); - Simulator::Destroy (); - - result = result && (rxBytes1 == test3_payloadSize); - - Reset(); -} -void -TcpSocketImplTest::Test3_HandleConnectionCreated (Ptr s, const Address &) -{ - NS_ASSERT(s != listeningSock); - NS_ASSERT(sock0 == 0); - sock0 = s; - Ptr p = Create (test3_payloadSize); - sock0->Send(p); -} -void -TcpSocketImplTest::Test3_HandleRecv (Ptr sock) -{ - NS_ASSERT_MSG (sock == sock1, "Not supposed to be back traffic in test 3... "); - if(sock->GetRxAvailable() >= 10000 ) //perform batch reads every 10000 bytes - { - Ptr p = sock->Recv(); - uint32_t sz = p->GetSize(); - rxBytes1 += sz; - } -} - -//----------------------------------------------------------------------------- -//helpers---------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Ptr -TcpSocketImplTest::CreateInternetNode () -{ - Ptr node = CreateObject (); - AddInternetStack (node); return node; } Ptr -TcpSocketImplTest::AddSimpleNetDevice (Ptr node, const char* ipaddr, const char* netmask) +TcpTestCase::AddSimpleNetDevice (Ptr node, const char* ipaddr, const char* netmask) { Ptr dev = CreateObject (); dev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ())); @@ -311,57 +275,53 @@ TcpSocketImplTest::AddSimpleNetDevice (Ptr node, const char* ipaddr, const return dev; } -void -TcpSocketImplTest::SetupDefaultSim () +void +TcpTestCase::SetupDefaultSim (void) { const char* netmask = "255.255.255.0"; const char* ipaddr0 = "192.168.1.1"; const char* ipaddr1 = "192.168.1.2"; - node0 = CreateInternetNode (); - node1 = CreateInternetNode (); - dev0 = AddSimpleNetDevice (node0, ipaddr0, netmask); - dev1 = AddSimpleNetDevice (node1, ipaddr1, netmask); + Ptr node0 = CreateInternetNode (); + Ptr node1 = CreateInternetNode (); + Ptr dev0 = AddSimpleNetDevice (node0, ipaddr0, netmask); + Ptr dev1 = AddSimpleNetDevice (node1, ipaddr1, netmask); - channel = CreateObject (); + Ptr channel = CreateObject (); dev0->SetChannel (channel); dev1->SetChannel (channel); Ptr sockFactory0 = node0->GetObject (); Ptr sockFactory1 = node1->GetObject (); - listeningSock = sockFactory0->CreateSocket(); - sock1 = sockFactory1->CreateSocket(); + Ptr server = sockFactory0->CreateSocket(); + Ptr source = sockFactory1->CreateSocket(); uint16_t port = 50000; InetSocketAddress serverlocaladdr (Ipv4Address::GetAny(), port); InetSocketAddress serverremoteaddr (Ipv4Address(ipaddr0), port); - listeningSock->Bind(serverlocaladdr); - listeningSock->Listen (); + server->Bind(serverlocaladdr); + server->Listen (); + server->SetAcceptCallback (MakeNullCallback, const Address &> (), + MakeCallback(&TcpTestCase::ServerHandleConnectionCreated,this)); - sock1->Connect(serverremoteaddr); + source->SetRecvCallback (MakeCallback(&TcpTestCase::SourceHandleRecv, this)); + source->SetSendCallback (MakeCallback (&TcpTestCase::SourceHandleSend, this)); + + source->Connect(serverremoteaddr); } -void -TcpSocketImplTest::Reset () +static class TcpTestSuite : public TestSuite { - node0 = 0; - node1 = 0; - dev0 = 0; - dev1 = 0; - channel = 0; - listeningSock = 0; - sock0 = 0; - sock1 = 0; - rxBytes0 = 0; - rxBytes1 = 0; - delete[] rxPayload; - rxPayload = 0; -} - -static TcpSocketImplTest gTcpSocketImplTest; - -}//namespace ns3 - -#endif /* RUN_SELF_TESTS */ +public: + TcpTestSuite () + : TestSuite ("tcp", UNIT) + { + AddTestCase (new TcpTestCase (13, 200, 200, 200, 200)); + AddTestCase (new TcpTestCase (13, 1, 1, 1, 1)); + //AddTestCase (new TcpTestCase (100000, 100, 50, 100, 20)); + } + +} g_tcpTestSuite; +} // namespace ns3