blob: bcc6d1555ed86d7d77fc89afc3a6b93580e10c7a [file] [log] [blame]
Pau Espin Pedrol83f52662019-06-20 17:05:27 +02001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <arpa/inet.h>
6
7#include <osmocom/core/utils.h>
8#include <osmocom/core/application.h>
9#include <osmocom/core/logging.h>
10#include <osmocom/core/msgb.h>
11#include <osmocom/core/bits.h>
12
13#include "../../lib/syserr.h"
14#include "../../gtp/queue.h"
15
16static const struct qmsg_t qmsg_zero;
17
18static void queue_print(struct queue_t *queue, char* str)
19{
20 int n;
21 printf("=== [Queue %s] Next: %d First: %d Last: %d\n", str,
22 queue->next, queue->first, queue->last);
23 printf("#\tseq\tnext\tprev\ttimeout\tretrans\ttype\tcbp\n");
24 for (n = 0; n < QUEUE_SIZE; n++) {
25 if (queue->qmsga[n].state == 0) {
26 /* Nothing there, validate everything is zeroed */
27 OSMO_ASSERT(memcmp(&qmsg_zero, &queue->qmsga[n], sizeof(qmsg_zero)) == 0);
28 continue;
29 }
30 printf("%d\t%d\t%d\t%d\t%d\t%d\t%u\t%ld\n",
31 n,
32 queue->qmsga[n].seq,
33 queue->qmsga[n].next,
34 queue->qmsga[n].prev,
35 (int)queue->qmsga[n].timeout,
36 queue->qmsga[n].retrans,
37 queue->qmsga[n].type,
38 ((uintptr_t)queue->qmsga[n].cbp & 0xFFFFFFFF)
39 );
40 }
41 printf("======================================================\n");
42}
43
44static void test_queue_empty()
45{
46 printf("***** Testing %s()\n", __func__);
47 struct queue_t *queue = NULL;
48 struct qmsg_t *qmsg = NULL;
49 uint16_t seq = 23;
50 uint8_t type = 0;
51 void *cbp = NULL;
52 struct sockaddr_in peer;
53 int rc;
54
55 rc = inet_pton(AF_INET, "127.0.0.1", &(peer.sin_addr));
56 OSMO_ASSERT(rc == 1);
57
58 rc = queue_new(&queue);
59 OSMO_ASSERT(rc == 0);
60 queue_print(queue, "created");
61
62 rc = queue_getfirst(queue, &qmsg);
63 OSMO_ASSERT(rc == EOF);
64 rc = queue_seqget(queue, &qmsg, &peer, seq);
65 OSMO_ASSERT(rc == EOF);
66 rc = queue_freemsg_seq(queue, &peer, seq, &type, &cbp);
67 OSMO_ASSERT(rc==EOF);
68
69 queue_print(queue, "pre-delete");
70 rc = queue_free(queue);
71 OSMO_ASSERT(rc == 0);
72}
73
74static void test_queue_one()
75{
76 printf("***** Testing %s()\n", __func__);
77 struct queue_t *queue = NULL;
78 struct qmsg_t *qmsg = NULL, *qmsg2 = NULL;;
79 uint16_t seq = 23;
80 uint8_t type = 0;
81 void *cbp = NULL;
82 struct sockaddr_in peer, peer2;
83 int rc;
84
85 rc = inet_pton(AF_INET, "127.0.0.1", &(peer.sin_addr));
86 OSMO_ASSERT(rc == 1);
87 rc = inet_pton(AF_INET, "127.0.0.2", &(peer2.sin_addr));
88 OSMO_ASSERT(rc == 1);
89
90 rc = queue_new(&queue);
91 OSMO_ASSERT(rc == 0);
92 queue_print(queue, "created");
93
94 rc = queue_newmsg(queue, &qmsg, &peer, seq);
95 OSMO_ASSERT(rc == 0);
96 queue_print(queue, "first added");
97 qmsg->type = GTP_ECHO_REQ;
98 qmsg->cbp = (void*) 0x13243546;
99 qmsg->seq = seq;
100
101 rc = queue_getfirst(queue, &qmsg2);
102 OSMO_ASSERT(rc == 0);
103 OSMO_ASSERT(qmsg == qmsg2);
104
105 rc = queue_seqget(queue, &qmsg2, &peer, seq);
106 OSMO_ASSERT(rc == 0);
107 OSMO_ASSERT(qmsg == qmsg2);
108 rc = queue_seqget(queue, &qmsg, &peer2, seq);
109 OSMO_ASSERT(rc == EOF);
110 rc = queue_seqget(queue, &qmsg, &peer, seq + 1);
111 OSMO_ASSERT(rc == EOF);
112 queue_print(queue, "after-get");
113
114 rc = queue_back(queue, qmsg);
115 OSMO_ASSERT(rc == 0);
116 queue_print(queue, "after-back");
117
118 rc = queue_freemsg_seq(queue, &peer2, seq, &type, &cbp);
119 OSMO_ASSERT(rc == EOF);
120 rc = queue_freemsg_seq(queue, &peer, seq + 1, &type, &cbp);
121 OSMO_ASSERT(rc == EOF);
122 queue_print(queue, "pree-freemsg");
123 rc = queue_freemsg_seq(queue, &peer, seq, &type, &cbp);
124 OSMO_ASSERT(rc == 0);
125 OSMO_ASSERT(type == GTP_ECHO_REQ);
126 OSMO_ASSERT(cbp == (void*)0x13243546);
127
128 queue_print(queue, "pre-delete");
129 rc = queue_free(queue);
130 OSMO_ASSERT(rc == 0);
131}
132
133#define newmsg_fill(queue, qmsg_ptr, peer_ptr, seq) \
134 do { \
135 int rc = queue_newmsg(queue, &(qmsg_ptr), peer_ptr, seq); \
136 OSMO_ASSERT(rc == 0); \
137 OSMO_ASSERT(qmsg_ptr); \
138 qmsg_ptr->type = GTP_CREATE_PDP_REQ; \
139 qmsg_ptr->cbp = (void*)(uintptr_t)seq; \
140 } while (0);
141
142#define freemsg_verify(seq, type, cbp) \
143 do { \
144 OSMO_ASSERT(type == GTP_CREATE_PDP_REQ); \
145 OSMO_ASSERT(cbp == (void*)(uintptr_t)seq); \
146 } while (0);
147
148static void test_queue_full()
149{
150 /* queue_newmsg until we receive EOF. Try moving back then. */
151 printf("***** Testing %s()\n", __func__);
152 struct queue_t *queue = NULL;
153 struct qmsg_t *qmsg = NULL;
154 uint8_t type = 0;
155 void *cbp = NULL;
156 struct sockaddr_in peer;
157 int rc;
158 int i;
159
160 rc = inet_pton(AF_INET, "127.0.0.1", &(peer.sin_addr));
161 OSMO_ASSERT(rc == 1);
162
163 rc = queue_new(&queue);
164 OSMO_ASSERT(rc == 0);
165 queue_print(queue, "created");
166
167 for (i = 0; i < QUEUE_SIZE - 1; i++) {
168 newmsg_fill(queue, qmsg, &peer, i);
169 }
170 queue_print(queue, "after-fill");
171
172 /* There's one slot left at the end, let's use first()->back() */
173 rc = queue_getfirst(queue, &qmsg);
174 OSMO_ASSERT(rc == 0);
175 rc = queue_back(queue, qmsg);
176 OSMO_ASSERT(rc == 0);
177 queue_print(queue, "after-back");
178
179 /* Now let's fill last empty slot */
180 newmsg_fill(queue, qmsg, &peer, QUEUE_SIZE - 1);
181 queue_print(queue, "after-full");
182
183 /* queue is now full, it should fail */
184 rc = queue_newmsg(queue, &qmsg, &peer, QUEUE_SIZE);
185 OSMO_ASSERT(rc == EOF);
186 queue_print(queue, "after-failing-full");
187
188 /* Remove 1before-last msg (the one moved back) and make sure we can
189 re-add it at the end of the list */
190 rc = queue_seqget(queue, &qmsg, &peer, 0);
191 OSMO_ASSERT(rc == 0);
192 rc = queue_freemsg(queue, qmsg);
193 queue_print(queue, "after-freeing-0");
194 OSMO_ASSERT(rc == 0);
195 /* Now let's fill last empty slot which should be at the end */
196 newmsg_fill(queue, qmsg, &peer, 0);
197 queue_print(queue, "after-refilling-0");
198
199 /* Now free first half seq set in increasing order */
200 for (i = 0; i < QUEUE_SIZE / 2; i++) {
201 rc = queue_freemsg_seq(queue, &peer, i, &type, &cbp);
202 OSMO_ASSERT(rc == 0);
203 freemsg_verify(i, type, cbp);
204 }
205 queue_print(queue, "after-first-half-free");
206
207 /* Now free second half seq set in decreasing order */
208 for (i = QUEUE_SIZE - 1; i >= QUEUE_SIZE / 2; i--) {
209 rc = queue_freemsg_seq(queue, &peer, i, &type, &cbp);
210 OSMO_ASSERT(rc == 0);
211 freemsg_verify(i, type, cbp);
212 }
213 queue_print(queue, "after-second-half-free");
214
215 rc = queue_free(queue);
216 OSMO_ASSERT(rc == 0);
217}
218
219int main(int argc, char **argv)
220{
221 void *tall_ctx = talloc_named_const(NULL, 1, "Root context");
222 msgb_talloc_ctx_init(tall_ctx, 0);
223 osmo_init_logging2(tall_ctx, &log_info);
224 log_set_use_color(osmo_stderr_target, 0);
225 log_set_print_filename(osmo_stderr_target, 0);
226
227 test_queue_empty();
228 test_queue_one();
229 test_queue_full();
230
231 return 0;
232}