]> git.llucax.com Git - software/posixx.git/blob - test/socket/generic_test.hpp
Add Boost License
[software/posixx.git] / test / socket / generic_test.hpp
1 // Copyright Leandro Lucarella 2008 - 2010.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file COPYING or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5
6
7
8 /*
9  * This file should be included from others, and the next symbols are expected
10  * to be defined:
11  *
12  * Preprocessor constants:
13  * - One of TEST_[socket type]
14  * - TEST_NS should be set to the namespace the socket family that will be used
15  * - TEST_PROTOCOL should be set to the socket's protocol to be tested
16  * - TEST_HAVE_PAIR should be defined if the socket family have a "pair()"
17  *   function.
18  * - TEST_CHECK_ADDR should be defined if name() should return the same
19  *   sockaddr used when bind()ing.
20  *
21  * Global variables:
22  * - test_address1 and test_address2 should be valid sockaddrs.
23  *
24  * Global functions:
25  * - void clean_test_address(TEST_NS::sock& socket, const TEST_NS::sockaddr&)
26  *   should be a function. It will be called before binding a socket to do any
27  *   cleanup task for a particular address to be used. Can be a macro.
28  * - std::ostream& operator << (std::ostream& os, const TEST_NS::sockaddr&)
29  *   should be defined.
30  */
31
32
33 #ifdef TEST_PF_UNIX
34 #undef TEST_PF_UNIX
35 #define TEST_PF_UNIX 1
36 #else
37 #define TEST_PF_UNIX 0
38 #endif
39 #ifdef TEST_PF_INET
40 #undef TEST_PF_INET
41 #define TEST_PF_INET 1
42 #else
43 #define TEST_PF_INET 0
44 #endif
45 #ifdef TEST_PF_TIPC
46 #undef TEST_PF_TIPC
47 #define TEST_PF_TIPC 1
48 #else
49 #define TEST_PF_TIPC 0
50 #endif
51
52 #ifdef TEST_DGRAM
53 #undef TEST_DGRAM
54 #define TEST_DGRAM 1
55 #else
56 #define TEST_DGRAM 0
57 #endif
58 #ifdef TEST_RDM
59 #undef TEST_RDM
60 #define TEST_RDM 1
61 #else
62 #define TEST_RDM 0
63 #endif
64 #ifdef TEST_STREAM
65 #undef TEST_STREAM
66 #define TEST_STREAM 1
67 #else
68 #define TEST_STREAM 0
69 #endif
70 #ifdef TEST_SEQPACKET
71 #undef TEST_SEQPACKET
72 #define TEST_SEQPACKET 1
73 #else
74 #define TEST_SEQPACKET 0
75 #endif
76 #ifdef TEST_RAW
77 #undef TEST_RAW
78 #define TEST_RAW 1
79 #else
80 #define TEST_RAW 0
81 #endif
82
83 #if TEST_DGRAM
84 #define TEST_TYPE ::posixx::socket::DGRAM
85 #endif
86 #if TEST_RDM
87 #define TEST_TYPE ::posixx::socket::RDM
88 #endif
89 #if TEST_STREAM
90 #define TEST_TYPE ::posixx::socket::STREAM
91 #endif
92 #if TEST_SEQPACKET
93 #define TEST_TYPE ::posixx::socket::SEQPACKET
94 #endif
95 #if TEST_RAW
96 #define TEST_TYPE ::posixx::socket::RAW
97 #endif
98
99
100 #if TEST_PF_UNIX // unix sockets are the only that provides pairs
101
102 BOOST_AUTO_TEST_CASE( pair_test )
103 {
104         TEST_NS::pair_type p = TEST_NS::pair(TEST_TYPE, TEST_PROTOCOL);
105         BOOST_CHECK_GE( p.first->fd(), 0 );
106         BOOST_CHECK_GE( p.second->fd(), 0 );
107         delete p.first;
108         delete p.second;
109 }
110
111 #endif // TEST_PF_UNIX
112
113 BOOST_AUTO_TEST_CASE( constructor_test )
114 {
115         TEST_NS::socket s(TEST_TYPE, TEST_PROTOCOL);
116         BOOST_CHECK_GE( s.fd(), 0 );
117 }
118
119 BOOST_AUTO_TEST_CASE( close_test )
120 {
121         TEST_NS::socket s(TEST_TYPE, TEST_PROTOCOL);
122         s.close();
123         BOOST_CHECK_EQUAL( s.fd(), -1 );
124 }
125
126 BOOST_AUTO_TEST_CASE( options_test )
127 {
128         using ::posixx::socket::opt::REUSEADDR;
129         TEST_NS::socket s(TEST_TYPE, TEST_PROTOCOL);
130         s.opt< REUSEADDR >(true);
131         BOOST_CHECK_GE( s.opt< REUSEADDR >(), true );
132 }
133
134 BOOST_AUTO_TEST_CASE( bind_test )
135 {
136         TEST_NS::socket s(TEST_TYPE, TEST_PROTOCOL);
137         clean_test_address(s, test_address1);
138         s.bind(test_address1);
139         s.name();
140 #if !TEST_PF_TIPC // TIPC returns a Port ID (and we use Port names)
141         BOOST_CHECK_EQUAL( s.name(), test_address1 );
142 #endif
143 }
144
145
146 #if TEST_SEQPACKET || TEST_STREAM
147
148 // TODO: test different flavors of send/recv.
149
150 BOOST_AUTO_TEST_CASE( listen_test )
151 {
152         TEST_NS::socket s(TEST_TYPE, TEST_PROTOCOL);
153         clean_test_address(s, test_address1);
154         s.bind(test_address1);
155         s.listen();
156 }
157
158 static inline
159 void set_blocking(int fd, bool blocking)
160 {
161         int flags = fcntl(fd, F_GETFL, 0);
162         assert(flags != -1);
163         if (blocking)
164                 fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
165         else
166                 fcntl(fd, F_SETFL, flags | O_NONBLOCK);
167 }
168
169 #if !TEST_PF_TIPC // TIPC can't connect a non-blocking socket
170 BOOST_AUTO_TEST_CASE( connect_accept_test )
171 {
172         TEST_NS::socket ss(TEST_TYPE, TEST_PROTOCOL);
173         clean_test_address(ss, test_address1);
174         ss.bind(test_address1);
175         ss.listen();
176         TEST_NS::socket sc(TEST_TYPE, TEST_PROTOCOL);
177         set_blocking(sc, false);
178         try {
179                 sc.connect(test_address1);
180         } catch (const posixx::error& e) {
181                 BOOST_REQUIRE_EQUAL( e.no, EINPROGRESS );
182         }
183         set_blocking(sc, true);
184         TEST_NS::socket* sa = ss.accept();
185         BOOST_CHECK_EQUAL( sc.peer_name(), test_address1 );
186         BOOST_CHECK_EQUAL( sc.peer_name(), sa->name() );
187 #if !TEST_PF_UNIX // Unix sockets has garbage in this addresses
188         BOOST_CHECK_EQUAL( sc.name(), sa->peer_name() );
189 #endif // TEST_PF_UNIX
190         delete sa;
191 }
192 #endif // !TEST_PF_TIPC
193
194 #endif // TEST_SEQPACKET || TEST_STREAM
195
196
197 #if TEST_DGRAM || TEST_RDM || TEST_RAW
198
199 BOOST_AUTO_TEST_CASE( dgram_sendto_recvfrom_test )
200 {
201         // socket 1
202         TEST_NS::socket s1(TEST_TYPE, TEST_PROTOCOL);
203         clean_test_address(s1, test_address1);
204         s1.bind(test_address1);
205         // socket 2
206         TEST_NS::socket s2(TEST_TYPE, TEST_PROTOCOL);
207         clean_test_address(s2, test_address2);
208         s2.bind(test_address2);
209         // socket 1 send
210         char buffer[] = "hello world!";
211         BOOST_CHECK_EQUAL( s1.send(buffer, sizeof(buffer), test_address2),
212                         sizeof(buffer) );
213         memset(buffer, 0, sizeof(buffer));
214         // socket 2 receive
215         TEST_NS::sockaddr addr;
216         BOOST_CHECK_EQUAL( s2.recv(buffer, sizeof(buffer), addr),
217                         sizeof(buffer) );
218         BOOST_CHECK_EQUAL( buffer, "hello world!" );
219 #if !TEST_PF_TIPC // TIPC returns a Port ID (and we use Port names)
220         BOOST_CHECK_EQUAL( addr, test_address1 );
221 #endif
222 }
223
224 struct data
225 {
226         char msg[20];
227         int number;
228 };
229
230 BOOST_AUTO_TEST_CASE( dgram_sendto_recvfrom_struct_test )
231 {
232         // socket 1
233         TEST_NS::socket s1(TEST_TYPE, TEST_PROTOCOL);
234         clean_test_address(s1, test_address1);
235         s1.bind(test_address1);
236         // socket 2
237         TEST_NS::socket s2(TEST_TYPE, TEST_PROTOCOL);
238         clean_test_address(s2, test_address2);
239         s2.bind(test_address2);
240         // socket 1 send
241         data d;
242         memset(&d, 0, sizeof(data));
243         strcpy(d.msg, "hello world!");
244         d.number = -32495813;
245         s1.send_struct(d, test_address2);
246         memset(&d, 0, sizeof(data));
247         // socket 2 receive
248         TEST_NS::sockaddr addr;
249         s2.recv_struct(d, addr);
250         BOOST_CHECK_EQUAL( d.msg, "hello world!" );
251         BOOST_CHECK_EQUAL( d.number, -32495813 );
252 }
253
254 #endif // TEST_DGRAM || TEST_RDM || TEST_RAW
255