]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lwip.git/blob - test/unit/tcp/test_tcp.c
fixed unit tests (one TCP test failed, removed comma at the end of array initializers)
[pes-rpp/rpp-lwip.git] / test / unit / tcp / test_tcp.c
1 #include "test_tcp.h"
2
3 #include "lwip/tcp_impl.h"
4 #include "lwip/stats.h"
5 #include "tcp_helper.h"
6
7 #if !LWIP_STATS || !TCP_STATS || !MEMP_STATS
8 #error "This tests needs TCP- and MEMP-statistics enabled"
9 #endif
10
11 /* Setups/teardown functions */
12
13 static void
14 tcp_setup(void)
15 {
16   tcp_remove_all();
17 }
18
19 static void
20 tcp_teardown(void)
21 {
22   netif_list = NULL;
23   tcp_remove_all();
24 }
25
26
27 /* Test functions */
28
29 /** Call tcp_new() and tcp_abort() and test memp stats */
30 START_TEST(test_tcp_new_abort)
31 {
32   struct tcp_pcb* pcb;
33   LWIP_UNUSED_ARG(_i);
34
35   fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
36
37   pcb = tcp_new();
38   fail_unless(pcb != NULL);
39   if (pcb != NULL) {
40     fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
41     tcp_abort(pcb);
42     fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
43   }
44 }
45 END_TEST
46
47 /** Create an ESTABLISHED pcb and check if receive callback is called */
48 START_TEST(test_tcp_recv_inseq)
49 {
50   struct test_tcp_counters counters;
51   struct tcp_pcb* pcb;
52   struct pbuf* p;
53   char data[] = {1, 2, 3, 4};
54   ip_addr_t remote_ip, local_ip;
55   u16_t data_len;
56   u16_t remote_port = 0x100, local_port = 0x101;
57   struct netif netif;
58   LWIP_UNUSED_ARG(_i);
59
60   /* initialize local vars */
61   memset(&netif, 0, sizeof(netif));
62   IP4_ADDR(&local_ip, 192, 168, 1, 1);
63   IP4_ADDR(&remote_ip, 192, 168, 1, 2);
64   data_len = sizeof(data);
65   /* initialize counter struct */
66   memset(&counters, 0, sizeof(counters));
67   counters.expected_data_len = data_len;
68   counters.expected_data = data;
69
70   /* create and initialize the pcb */
71   pcb = test_tcp_new_counters_pcb(&counters);
72   EXPECT_RET(pcb != NULL);
73   tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
74
75   /* create a segment */
76   p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0);
77   EXPECT(p != NULL);
78   if (p != NULL) {
79     /* pass the segment to tcp_input */
80     test_tcp_input(p, &netif);
81     /* check if counters are as expected */
82     EXPECT(counters.close_calls == 0);
83     EXPECT(counters.recv_calls == 1);
84     EXPECT(counters.recved_bytes == data_len);
85     EXPECT(counters.err_calls == 0);
86   }
87
88   /* make sure the pcb is freed */
89   EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
90   tcp_abort(pcb);
91   EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
92 }
93 END_TEST
94
95 /** Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data.
96  * At the end, send more data. */
97 START_TEST(test_tcp_fast_retx_recover)
98 {
99   struct netif netif;
100   struct test_tcp_txcounters txcounters;
101   struct test_tcp_counters counters;
102   struct tcp_pcb* pcb;
103   struct pbuf* p;
104   char data1[] = { 1,  2,  3,  4};
105   char data2[] = { 5,  6,  7,  8};
106   char data3[] = { 9, 10, 11, 12};
107   char data4[] = {13, 14, 15, 16};
108   char data5[] = {17, 18, 19, 20};
109   char data6[] = {21, 22, 23, 24};
110   ip_addr_t remote_ip, local_ip, netmask;
111   u16_t remote_port = 0x100, local_port = 0x101;
112   err_t err;
113   LWIP_UNUSED_ARG(_i);
114
115   /* initialize local vars */
116   IP4_ADDR(&local_ip,  192, 168,   1, 1);
117   IP4_ADDR(&remote_ip, 192, 168,   1, 2);
118   IP4_ADDR(&netmask,   255, 255, 255, 0);
119   test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask);
120   memset(&counters, 0, sizeof(counters));
121
122   /* create and initialize the pcb */
123   pcb = test_tcp_new_counters_pcb(&counters);
124   EXPECT_RET(pcb != NULL);
125   tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
126   pcb->mss = TCP_MSS;
127   /* disable initial congestion window (we don't send a SYN here...) */
128   pcb->cwnd = pcb->snd_wnd;
129   //tcp_nagle_disable(pcb);
130
131   /* send data1 */
132   err = tcp_write(pcb, data1, sizeof(data1), TCP_WRITE_FLAG_COPY);
133   EXPECT_RET(err == ERR_OK);
134   err = tcp_output(pcb);
135   EXPECT_RET(err == ERR_OK);
136   EXPECT_RET(txcounters.num_tx_calls == 1);
137   EXPECT_RET(txcounters.num_tx_bytes == sizeof(data1) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
138   memset(&txcounters, 0, sizeof(txcounters));
139  /* "recv" ACK for data1 */
140   p = tcp_create_rx_segment(pcb, NULL, 0, 0, 4, TCP_ACK);
141   EXPECT_RET(p != NULL);
142   test_tcp_input(p, &netif);
143   EXPECT_RET(txcounters.num_tx_calls == 0);
144   EXPECT_RET(pcb->unacked == NULL);
145   /* send data2 */
146   err = tcp_write(pcb, data2, sizeof(data2), TCP_WRITE_FLAG_COPY);
147   EXPECT_RET(err == ERR_OK);
148   err = tcp_output(pcb);
149   EXPECT_RET(err == ERR_OK);
150   EXPECT_RET(txcounters.num_tx_calls == 1);
151   EXPECT_RET(txcounters.num_tx_bytes == sizeof(data2) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
152   memset(&txcounters, 0, sizeof(txcounters));
153   /* duplicate ACK for data1 (data2 is lost) */
154   p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
155   EXPECT_RET(p != NULL);
156   test_tcp_input(p, &netif);
157   EXPECT_RET(txcounters.num_tx_calls == 0);
158   EXPECT_RET(pcb->dupacks == 1);
159   /* send data3 */
160   err = tcp_write(pcb, data3, sizeof(data3), TCP_WRITE_FLAG_COPY);
161   EXPECT_RET(err == ERR_OK);
162   err = tcp_output(pcb);
163   EXPECT_RET(err == ERR_OK);
164   /* nagle enabled, no tx calls */
165   EXPECT_RET(txcounters.num_tx_calls == 0);
166   EXPECT_RET(txcounters.num_tx_bytes == 0);
167   memset(&txcounters, 0, sizeof(txcounters));
168   /* 2nd duplicate ACK for data1 (data2 and data3 are lost) */
169   p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
170   EXPECT_RET(p != NULL);
171   test_tcp_input(p, &netif);
172   EXPECT_RET(txcounters.num_tx_calls == 0);
173   EXPECT_RET(pcb->dupacks == 2);
174   /* queue data4, don't send it (unsent-oversize is != 0) */
175   err = tcp_write(pcb, data4, sizeof(data4), TCP_WRITE_FLAG_COPY);
176   EXPECT_RET(err == ERR_OK);
177   /* 3nd duplicate ACK for data1 (data2 and data3 are lost) -> fast retransmission */
178   p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
179   EXPECT_RET(p != NULL);
180   test_tcp_input(p, &netif);
181   //EXPECT_RET(txcounters.num_tx_calls == 1);
182   EXPECT_RET(pcb->dupacks == 3);
183   memset(&txcounters, 0, sizeof(txcounters));
184   // TODO: check expected data?
185   
186   /* send data5, not output yet */
187   err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
188   EXPECT_RET(err == ERR_OK);
189   //err = tcp_output(pcb);
190   //EXPECT_RET(err == ERR_OK);
191   EXPECT_RET(txcounters.num_tx_calls == 0);
192   EXPECT_RET(txcounters.num_tx_bytes == 0);
193   memset(&txcounters, 0, sizeof(txcounters));
194   {
195     int i = 0;
196     do
197     {
198       err = tcp_write(pcb, data6, TCP_MSS, TCP_WRITE_FLAG_COPY);
199       i++;
200     }while(err == ERR_OK);
201     EXPECT_RET(err != ERR_OK);
202   }
203   err = tcp_output(pcb);
204   EXPECT_RET(err == ERR_OK);
205   //EXPECT_RET(txcounters.num_tx_calls == 0);
206   //EXPECT_RET(txcounters.num_tx_bytes == 0);
207   memset(&txcounters, 0, sizeof(txcounters));
208
209   /* send even more data */
210   err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
211   EXPECT_RET(err == ERR_OK);
212   err = tcp_output(pcb);
213   EXPECT_RET(err == ERR_OK);
214   /* ...and even more data */
215   err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
216   EXPECT_RET(err == ERR_OK);
217   err = tcp_output(pcb);
218   EXPECT_RET(err == ERR_OK);
219   /* ...and even more data */
220   err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
221   EXPECT_RET(err == ERR_OK);
222   err = tcp_output(pcb);
223   EXPECT_RET(err == ERR_OK);
224   /* ...and even more data */
225   err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
226   EXPECT_RET(err == ERR_OK);
227   err = tcp_output(pcb);
228   EXPECT_RET(err == ERR_OK);
229
230   /* send ACKs for data2 and data3 */
231   p = tcp_create_rx_segment(pcb, NULL, 0, 0, 12, TCP_ACK);
232   EXPECT_RET(p != NULL);
233   test_tcp_input(p, &netif);
234   //EXPECT_RET(txcounters.num_tx_calls == 0);
235
236   /* ...and even more data */
237   err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
238   EXPECT_RET(err == ERR_OK);
239   err = tcp_output(pcb);
240   EXPECT_RET(err == ERR_OK);
241   /* ...and even more data */
242   err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
243   EXPECT_RET(err == ERR_OK);
244   err = tcp_output(pcb);
245   EXPECT_RET(err == ERR_OK);
246
247 #if 0
248   /* create expected segment */
249   p1 = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0);
250   EXPECT_RET(p != NULL);
251   if (p != NULL) {
252     /* pass the segment to tcp_input */
253     test_tcp_input(p, &netif);
254     /* check if counters are as expected */
255     EXPECT_RET(counters.close_calls == 0);
256     EXPECT_RET(counters.recv_calls == 1);
257     EXPECT_RET(counters.recved_bytes == data_len);
258     EXPECT_RET(counters.err_calls == 0);
259   }
260 #endif
261   /* make sure the pcb is freed */
262   EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
263   tcp_abort(pcb);
264   EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
265 }
266 END_TEST
267
268
269 /** Create the suite including all tests for this module */
270 Suite *
271 tcp_suite(void)
272 {
273   TFun tests[] = {
274     test_tcp_new_abort,
275     test_tcp_recv_inseq,
276     test_tcp_fast_retx_recover
277   };
278   return create_suite("TCP", tests, sizeof(tests)/sizeof(TFun), tcp_setup, tcp_teardown);
279 }