diff --git a/src/modules/udp_transport/source/udp_socket_manager_unittest.cc b/src/modules/udp_transport/source/udp_socket_manager_unittest.cc index 035fff0515..21c1a4e532 100644 --- a/src/modules/udp_transport/source/udp_socket_manager_unittest.cc +++ b/src/modules/udp_transport/source/udp_socket_manager_unittest.cc @@ -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 diff --git a/src/modules/udp_transport/source/udp_socket_wrapper.h b/src/modules/udp_transport/source/udp_socket_wrapper.h index 9a3b585d69..e5289cf649 100644 --- a/src/modules/udp_transport/source/udp_socket_wrapper.h +++ b/src/modules/udp_transport/source/udp_socket_wrapper.h @@ -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; diff --git a/src/modules/udp_transport/source/udp_socket_wrapper_unittest.cc b/src/modules/udp_transport/source/udp_socket_wrapper_unittest.cc new file mode 100644 index 0000000000..32d9a6484b --- /dev/null +++ b/src/modules/udp_transport/source/udp_socket_wrapper_unittest.cc @@ -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 diff --git a/src/modules/udp_transport/source/udp_transport.gypi b/src/modules/udp_transport/source/udp_transport.gypi index cb109deff6..90ac4839e9 100644 --- a/src/modules/udp_transport/source/udp_transport.gypi +++ b/src/modules/udp_transport/source/udp_transport.gypi @@ -108,6 +108,7 @@ 'sources': [ 'udp_transport_unittest.cc', 'udp_socket_manager_unittest.cc', + 'udp_socket_wrapper_unittest.cc', ], }, # udp_transport_unittests ], # targets