Added an unittest for udp_socket_wrapper.

This involves checking what the reasonable call sequences for deleting a
socket is; documented the API for this by making the destructor protected.
Checked out that the behaviour of undeleted sockets is inconsistent across
platforms, and changed the udp_socket_manager_unittest accordingly.

BUG=
TEST=

Review URL: https://webrtc-codereview.appspot.com/578007

git-svn-id: http://webrtc.googlecode.com/svn/trunk@2236 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
hta@webrtc.org 2012-05-14 16:03:37 +00:00
parent f6ec0a91a2
commit 93116ba4fc
4 changed files with 132 additions and 19 deletions

View File

@ -18,15 +18,18 @@
#include "udp_socket_wrapper.h"
#include "udp_socket_manager_wrapper.h"
#include "gtest/gtest.h"
#include "src/system_wrappers/interface/trace.h"
namespace webrtc {
TEST(UdpSocketManager, CreateCallsInitAndDoesNotLeakMemory) {
WebRtc_Word32 id = 42;
WebRtc_UWord8 threads = 1;
webrtc::UdpSocketManager* mgr = webrtc::UdpSocketManager::Create(id, threads);
UdpSocketManager* mgr = UdpSocketManager::Create(id, threads);
// Create is supposed to have called init on the object.
EXPECT_EQ(false, mgr->Init(id, threads))
<< "Init should return false since Create is supposed to call it.";
webrtc::UdpSocketManager::Return();
UdpSocketManager::Return();
}
// Creates a socket and adds it to the socket manager, and then removes it
@ -34,28 +37,34 @@ TEST(UdpSocketManager, CreateCallsInitAndDoesNotLeakMemory) {
TEST(UdpSocketManager, AddAndRemoveSocketDoesNotLeakMemory) {
WebRtc_Word32 id = 42;
WebRtc_UWord8 threads = 1;
webrtc::UdpSocketManager* mgr = webrtc::UdpSocketManager::Create(id, threads);
webrtc::UdpSocketWrapper* socket
= webrtc::UdpSocketWrapper::CreateSocket(id,
mgr,
NULL, // CallbackObj
NULL, // IncomingSocketCallback
false, // ipV6Enable
false); // disableGQOS
UdpSocketManager* mgr = UdpSocketManager::Create(id, threads);
UdpSocketWrapper* socket
= UdpSocketWrapper::CreateSocket(id,
mgr,
NULL, // CallbackObj
NULL, // IncomingSocketCallback
false, // ipV6Enable
false); // disableGQOS
// The constructor will do AddSocket on the manager.
// RemoveSocket indirectly calls Delete.
EXPECT_EQ(true, mgr->RemoveSocket(socket));
webrtc::UdpSocketManager::Return();
UdpSocketManager::Return();
}
// Creates a socket and add it to the socket manager, but does not remove it
// before destroying the socket manager.
// This should also destroy the socket.
TEST(UdpSocketManager, DISABLED_UnremovedSocketsGetCollectedAtManagerDeletion) {
// On Posix, this destroys the socket.
// On Winsock2 Windows, it enters an infinite wait for all the sockets
// to go away.
TEST(UdpSocketManager, UnremovedSocketsGetCollectedAtManagerDeletion) {
#if defined(_WIN32)
// It's hard to test an infinite wait, so we don't.
#else
WebRtc_Word32 id = 42;
WebRtc_UWord8 threads = 1;
webrtc::UdpSocketManager* mgr = webrtc::UdpSocketManager::Create(id, threads);
webrtc::UdpSocketWrapper* unused_socket
= webrtc::UdpSocketWrapper::CreateSocket(id,
UdpSocketManager* mgr = UdpSocketManager::Create(id, threads);
UdpSocketWrapper* unused_socket
= UdpSocketWrapper::CreateSocket(id,
mgr,
NULL, // CallbackObj
NULL, // IncomingSocketCallback
@ -63,5 +72,8 @@ TEST(UdpSocketManager, DISABLED_UnremovedSocketsGetCollectedAtManagerDeletion) {
false); // disableGQOS
// The constructor will do AddSocket on the manager.
unused_socket = NULL;
webrtc::UdpSocketManager::Return();
UdpSocketManager::Return();
#endif
}
} // namespace webrtc

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
@ -40,7 +40,6 @@ typedef void(*IncomingSocketCallback)(CallbackObj obj, const WebRtc_Word8* buf,
class UdpSocketWrapper
{
public:
virtual ~UdpSocketWrapper();
static UdpSocketWrapper* CreateSocket(const WebRtc_Word32 id,
UdpSocketManager* mgr,
CallbackObj obj,
@ -97,7 +96,10 @@ public:
virtual WebRtc_UWord32 ReceiveBuffers() {return 0;};
protected:
// Creating the socket is done via CreateSocket().
UdpSocketWrapper();
// Destroying the socket is done via CloseBlocking().
virtual ~UdpSocketWrapper();
bool _wantsIncoming;
EventWrapper* _deleteEvent;

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// Tests for the UdpSocketWrapper interface.
// This will test the UdpSocket implementations on various platforms.
// Note that this test is using a real SocketManager, which starts up
// an extra worker thread, making the testing more complex than it
// should be.
// This is because on Posix, the CloseBlocking function waits for the
// ReadyForDeletion function to be called, which has to be called after
// CloseBlocking, and thus has to be called from another thread.
// The manager is the one actually doing the deleting.
// This is done differently in the Winsock2 code, but that code
// will also hang if the destructor is called directly.
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "modules/udp_transport/source/udp_socket_wrapper.h"
#include "modules/udp_transport/source/udp_socket_manager_wrapper.h"
#include "system_wrappers/interface/trace.h"
using ::testing::_;
using ::testing::Return;
namespace webrtc {
const int kLogTrace = 0;
class TestTraceCallback: public TraceCallback {
public:
void Print(const TraceLevel level,
const char *traceString,
const int length) {
if (traceString) {
char* tmp = new char[length+1];
memcpy(tmp, traceString, length);
tmp[length] = '\0';
printf("%s\n", tmp);
fflush(stdout);
delete[] tmp;
}
}
};
class MockSocketManager : public UdpSocketManager {
public:
MockSocketManager() {}
// Access to protected destructor.
void Destroy() {
delete this;
}
MOCK_METHOD2(Init, bool(WebRtc_Word32, WebRtc_UWord8&));
MOCK_METHOD1(ChangeUniqueId, WebRtc_Word32(const WebRtc_Word32));
MOCK_METHOD0(Start, bool());
MOCK_METHOD0(Stop, bool());
MOCK_METHOD1(AddSocket, bool(webrtc::UdpSocketWrapper*));
MOCK_METHOD1(RemoveSocket, bool(webrtc::UdpSocketWrapper*));
};
// Creates a socket using the static constructor method and verifies that
// it's added to the socket manager.
TEST(UdpSocketWrapper, CreateSocket) {
TestTraceCallback trace;
if (kLogTrace) {
Trace::CreateTrace();
Trace::SetLevelFilter(webrtc::kTraceAll);
Trace::SetTraceCallback(&trace);
}
WebRtc_Word32 id = 42;
// We can't test deletion of sockets without a socket manager.
WebRtc_UWord8 threads = 1;
UdpSocketManager* mgr = UdpSocketManager::Create(id, threads);
WEBRTC_TRACE(kTraceMemory, kTraceTransport, 42,
"Test trace call");
UdpSocketWrapper* socket
= UdpSocketWrapper::CreateSocket(id,
mgr,
NULL, // CallbackObj
NULL, // IncomingSocketCallback
false, // ipV6Enable
false); // disableGQOS
socket->CloseBlocking();
UdpSocketManager::Return();
if (kLogTrace) {
Trace::ReturnTrace();
}
}
} // namespace webrtc

View File

@ -108,6 +108,7 @@
'sources': [
'udp_transport_unittest.cc',
'udp_socket_manager_unittest.cc',
'udp_socket_wrapper_unittest.cc',
],
}, # udp_transport_unittests
], # targets