Open Lighting Architecture
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MockUDPSocket.h
1 /*
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  *
7  * This library is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10  * Lesser General Public License for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public
13  * License along with this library; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15  *
16  * MockUDPsocket.h
17  * Header file for the Mock UDP Socket class
18  * Copyright (C) 2010 Simon Newton
19  */
20 
21 #ifndef INCLUDE_OLA_TESTING_MOCKUDPSOCKET_H_
22 #define INCLUDE_OLA_TESTING_MOCKUDPSOCKET_H_
23 
24 #include <cppunit/extensions/HelperMacros.h>
25 #include <string>
26 #include <queue>
27 
28 #include "ola/network/IPV4Address.h"
29 #include "ola/network/Socket.h"
30 #include "ola/network/SocketAddress.h"
31 
32 namespace ola {
33 namespace testing {
34 
35 using ola::io::IOQueue;
39 
40 /*
41  * The MockUDPSocket allows one to stub out a UDP Socket for testing. The
42  * code-under-test can use this object as it would a UDP socket, and the code
43  * performing the test can verify that the data written matches what it
44  * expects. It does this by calling AddExpectedData(), e.g.
45  *
46  * // add the data we expect, you can call this more than once
47  * udp_socket.AddExpectedData(....);
48  * udp_socket.AddExpectedData(....);
49  * // this calls one of the SendTo methods
50  * MethodToTest(udp_socket);
51  * // verify all the expected data has been consumed
52  * udp_socket.Verify()
53  *
54  * You can also inject packets into the socket by calling InjectData(), this
55  * will trigger the on_read callback that was attached to the socket.
56  */
58  public:
59  MockUDPSocket();
60  ~MockUDPSocket() { Close(); }
61 
62  // These are the socket methods
63  bool Init();
64  bool Bind(const ola::network::IPV4SocketAddress &endpoint);
65  bool GetSocketAddress(IPV4SocketAddress *address) const;
66  bool Close();
67  int ReadDescriptor() const { return m_dummy_sd; }
68  int WriteDescriptor() const { return m_dummy_sd; }
69  ssize_t SendTo(const uint8_t *buffer,
70  unsigned int size,
71  const ola::network::IPV4Address &ip,
72  unsigned short port) const;
73  ssize_t SendTo(const uint8_t *buffer,
74  unsigned int size,
75  const IPV4SocketAddress &dest) const {
76  return SendTo(buffer, size, dest.Host(), dest.Port());
77  }
78  ssize_t SendTo(IOVecInterface *data,
79  const ola::network::IPV4Address &ip,
80  unsigned short port) const;
81  ssize_t SendTo(IOVecInterface *data,
82  const IPV4SocketAddress &dest) const {
83  return SendTo(data, dest.Host(), dest.Port());
84  }
85 
86  bool RecvFrom(uint8_t *buffer, ssize_t *data_read) const;
87  bool RecvFrom(uint8_t *buffer,
88  ssize_t *data_read,
89  ola::network::IPV4Address &source) const;
90  bool RecvFrom(uint8_t *buffer,
91  ssize_t *data_read,
93  uint16_t &port) const;
94  bool EnableBroadcast();
95  bool SetMulticastInterface(const IPV4Address &interface);
96  bool JoinMulticast(const IPV4Address &interface,
97  const IPV4Address &group,
98  bool loop = false);
99  bool LeaveMulticast(const IPV4Address &interface,
100  const IPV4Address &group);
101 
102  bool SetTos(uint8_t tos);
103 
104  void SetDiscardMode(bool discard_mode) { m_discard_mode = discard_mode; }
105 
106  // these are methods used for verification
107  void AddExpectedData(const uint8_t *data,
108  unsigned int size,
109  const IPV4Address &ip,
110  uint16_t port);
111  void AddExpectedData(IOQueue *queue, const IPV4SocketAddress &dest);
112 
113  // this can be fetched by calling PerformRead() on the socket
114  void InjectData(const uint8_t *data,
115  unsigned int size,
116  const IPV4Address &ip,
117  uint16_t port);
118  void InjectData(const uint8_t *data,
119  unsigned int size,
120  const IPV4SocketAddress &source);
121  void InjectData(IOQueue *ioqueue, const IPV4SocketAddress &source);
122 
123  void Verify();
124 
125  bool CheckNetworkParamsMatch(bool init_called,
126  bool bound_to_port,
127  uint16_t port,
128  bool broadcast_set);
129 
130  void SetInterface(const IPV4Address &interface);
131 
132  private:
133  typedef struct {
134  const uint8_t *data;
135  unsigned int size;
136  IPV4Address address;
137  uint16_t port;
138  bool free_data;
139  } expected_call;
140 
141  typedef expected_call received_data;
142 
143  bool m_init_called;
144  // We need a sd so that calls to select continue to work. This isn't used
145  // for anything else.
146  int m_dummy_sd;
147  bool m_bound_to_port;
148  bool m_broadcast_set;
149  uint16_t m_port;
150  uint8_t m_tos;
151  mutable std::queue<expected_call> m_expected_calls;
152  mutable std::queue<received_data> m_received_data;
153  IPV4Address m_interface;
154  bool m_discard_mode;
155 
156  uint8_t* IOQueueToBuffer(IOQueue *ioqueue, unsigned int *size) const;
157 };
158 
159 
164  public:
165  explicit SocketVerifier(MockUDPSocket *socket)
166  : m_socket(socket) {
167  }
168  ~SocketVerifier() {
169  m_socket->Verify();
170  }
171 
172  private:
173  MockUDPSocket *m_socket;
174 };
175 } // namespace testing
176 } // namespace ola
177 #endif // INCLUDE_OLA_TESTING_MOCKUDPSOCKET_H_