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