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