1/*
2 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include <vector>
12
13#include "testing/gmock/include/gmock/gmock.h"
14#include "testing/gtest/include/gtest/gtest.h"
15#include "webrtc/test/channel_transport/udp_transport.h"
16// We include the implementation header file to get at the dependency-injecting
17// constructor.
18#include "webrtc/test/channel_transport/udp_transport_impl.h"
19// We must mock the socket manager, for which we need its definition.
20#include "webrtc/test/channel_transport/udp_socket_manager_wrapper.h"
21
22using ::testing::_;
23using ::testing::Return;
24
25namespace webrtc {
26namespace test {
27
28class MockUdpSocketWrapper : public UdpSocketWrapper {
29 public:
30  // The following methods have to be mocked because they are pure.
31  MOCK_METHOD1(ChangeUniqueId, int32_t(int32_t));
32  MOCK_METHOD2(SetCallback, bool(CallbackObj, IncomingSocketCallback));
33  MOCK_METHOD1(Bind, bool(const SocketAddress&));
34  MOCK_METHOD0(ValidHandle, bool());
35  MOCK_METHOD4(SetSockopt, bool(int32_t, int32_t,
36                                const int8_t*,
37                                int32_t));
38  MOCK_METHOD1(SetTOS, int32_t(int32_t));
39  MOCK_METHOD3(SendTo, int32_t(const int8_t*, int32_t, const SocketAddress&));
40  MOCK_METHOD8(SetQos, bool(int32_t, int32_t,
41                            int32_t, int32_t,
42                            int32_t, int32_t,
43                            const SocketAddress &,
44                            int32_t));
45};
46
47class MockUdpSocketManager : public UdpSocketManager {
48 public:
49  // Access to protected destructor.
50  void Destroy() {
51    delete this;
52  }
53  MOCK_METHOD2(Init, bool(int32_t, uint8_t&));
54  MOCK_METHOD1(ChangeUniqueId, int32_t(const int32_t));
55  MOCK_METHOD0(Start, bool());
56  MOCK_METHOD0(Stop, bool());
57  MOCK_METHOD1(AddSocket, bool(UdpSocketWrapper*));
58  MOCK_METHOD1(RemoveSocket, bool(UdpSocketWrapper*));
59};
60
61class MockSocketFactory :
62    public UdpTransportImpl::SocketFactoryInterface {
63 public:
64  MockSocketFactory(std::vector<MockUdpSocketWrapper*>* socket_counter)
65      : socket_counter_(socket_counter) {
66  }
67  UdpSocketWrapper* CreateSocket(const int32_t id,
68                                 UdpSocketManager* mgr,
69                                 CallbackObj obj,
70                                 IncomingSocketCallback cb,
71                                 bool ipV6Enable,
72                                 bool disableGQOS) {
73    MockUdpSocketWrapper* socket = new MockUdpSocketWrapper();
74    // We instrument the socket with calls that are expected, but do
75    // not matter for any specific test, in order to avoid warning messages.
76    EXPECT_CALL(*socket, ValidHandle()).WillRepeatedly(Return(true));
77    EXPECT_CALL(*socket, Bind(_)).WillOnce(Return(true));
78    socket_counter_->push_back(socket);
79    return socket;
80  }
81  std::vector<MockUdpSocketWrapper*>* socket_counter_;
82};
83
84class UDPTransportTest : public ::testing::Test {
85 public:
86  UDPTransportTest()
87      : sockets_created_(0) {
88  }
89
90  ~UDPTransportTest() {
91    // In production, sockets register themselves at creation time with
92    // an UdpSocketManager, and the UdpSocketManager is responsible for
93    // deleting them. In this test, we just delete them after the test.
94    while (!sockets_created_.empty()) {
95      delete sockets_created_.back();
96      sockets_created_.pop_back();
97    }
98  }
99
100  int NumSocketsCreated() {
101    return sockets_created_.size();
102  }
103
104  std::vector<MockUdpSocketWrapper*>* sockets_created() {
105    return &sockets_created_;
106  }
107private:
108  std::vector<MockUdpSocketWrapper*> sockets_created_;
109};
110
111TEST_F(UDPTransportTest, CreateTransport) {
112  int32_t id = 0;
113  uint8_t threads = 1;
114  UdpTransport* transport = UdpTransport::Create(id, threads);
115  UdpTransport::Destroy(transport);
116}
117
118// This test verifies that the mock_socket is not called from the constructor.
119TEST_F(UDPTransportTest, ConstructorDoesNotCreateSocket) {
120  int32_t id = 0;
121  UdpTransportImpl::SocketFactoryInterface* null_maker = NULL;
122  UdpSocketManager* null_manager = NULL;
123  UdpTransport* transport = new UdpTransportImpl(id,
124                                                 null_maker,
125                                                 null_manager);
126  delete transport;
127}
128
129TEST_F(UDPTransportTest, InitializeSourcePorts) {
130  int32_t id = 0;
131  UdpTransportImpl::SocketFactoryInterface* mock_maker
132      = new MockSocketFactory(sockets_created());
133  MockUdpSocketManager* mock_manager = new MockUdpSocketManager();
134  UdpTransport* transport = new UdpTransportImpl(id,
135                                                 mock_maker,
136                                                 mock_manager);
137  EXPECT_EQ(0, transport->InitializeSourcePorts(4711, 4712));
138  EXPECT_EQ(2, NumSocketsCreated());
139
140  delete transport;
141  mock_manager->Destroy();
142}
143
144}  // namespace test
145}  // namespace webrtc
146