a2c4873c37cac18ea92463c1c07b61887cad2132
[strongswan.git] / Source / charon / tests / ike_sa_manager_test.c
1 /**
2 * @file ike_sa_manager_test.c
3 *
4 * @brief Tests to test the IKE_SA-Manager type ike_sa_manager_t
5 *
6 */
7
8 /*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include <string.h>
24 #include <pthread.h>
25 #include <unistd.h>
26
27 #include "ike_sa_manager_test.h"
28 #include "../types.h"
29 #include "../tester.h"
30 #include "../ike_sa_manager.h"
31
32
33 static struct ike_sa_manager_test_struct_s {
34 tester_t *tester;
35 ike_sa_manager_t *isam;
36 } td;
37
38 static void test1_thread(ike_sa_id_t *ike_sa_id)
39 {
40 ike_sa_t *ike_sa;
41 status_t status;
42
43 status = td.isam->checkout(td.isam, ike_sa_id, &ike_sa);
44 td.tester->assert_true(td.tester, (status == SUCCESS), "checkout of a blocked ike_sa");
45 usleep(10000);
46 status = td.isam->checkin(td.isam, ike_sa);
47 td.tester->assert_true(td.tester, (status == SUCCESS), "checkin of a requested ike_sa");
48 }
49
50
51 static void test2_thread(ike_sa_id_t *ike_sa_id)
52 {
53 ike_sa_t *ike_sa;
54 status_t status;
55
56 status = td.isam->checkout(td.isam, ike_sa_id, &ike_sa);
57 td.tester->assert_true(td.tester, (status == NOT_FOUND), "IKE_SA already deleted");
58 }
59
60 static void test3_thread(ike_sa_id_t *ike_sa_id)
61 {
62 ike_sa_t *ike_sa;
63 status_t status;
64
65 status = td.isam->checkout(td.isam, ike_sa_id, &ike_sa);
66 td.tester->assert_true(td.tester, (status == NOT_FOUND), "IKE_SA already deleted");
67
68 ike_sa_id->destroy(ike_sa_id);
69 }
70
71
72
73
74 void test_ike_sa_manager(tester_t *tester)
75 {
76 status_t status;
77 spi_t initiator, responder;
78 ike_sa_id_t *ike_sa_id, *sa_id;
79 ike_sa_t *ike_sa;
80 int thread_count = 200;
81 int sa_count = 100;
82 int i;
83 pthread_t threads[thread_count];
84
85 td.tester = tester;
86 td.isam = ike_sa_manager_create();
87 tester->assert_true(tester, (td.isam != NULL), "ike_sa_manager creation");
88
89
90
91
92 /* First Test:
93 * we play initiator for IKE_SA_INIT first
94 * create an IKE_SA,
95 *
96 */
97 memset(&initiator, 0, sizeof(initiator));
98 memset(&responder, 0, sizeof(responder));
99
100 ike_sa_id = ike_sa_id_create(initiator, responder, INITIATOR);
101
102 status = td.isam->checkout(td.isam, ike_sa_id, &ike_sa);
103 tester->assert_true(tester, (status == SUCCESS), "checkout unexisting IKE_SA");
104 /* for testing purposes, we manipulate the responder spi.
105 * this is usually done be the response from the communication partner,
106 * but we don't have one...
107 */
108 responder.low = 123;
109
110 sa_id = ike_sa->get_id(ike_sa);
111 sa_id->set_responder_spi(sa_id, responder);
112 /* check in, so we should have a "completed" sa, specified by ike_sa_id */
113 status = td.isam->checkin(td.isam, ike_sa);
114 tester->assert_true(tester, (status == SUCCESS), "checkin modified IKE_SA");
115
116 /* now we check it out and start some other threads */
117 status = td.isam->checkout(td.isam, ike_sa_id, &ike_sa);
118 tester->assert_true(tester, (status == SUCCESS), "checkout existing IKE_SA 1");
119
120 for (i = 0; i < thread_count; i++)
121 {
122 if (pthread_create(&threads[i], NULL, (void*(*)(void*))test1_thread, (void*)ike_sa_id))
123 {
124 /* failed, decrease list */
125 thread_count--;
126 i--;
127 }
128 }
129 sleep(1);
130
131
132 status = td.isam->checkin(td.isam, ike_sa);
133 tester->assert_true(tester, (status == SUCCESS), "checkin IKE_SA");
134
135
136 sleep(1);
137 /* we now delete the IKE_SA, while it is requested by the threads.
138 * this should block until the have done their work.*/
139 status = td.isam->delete(td.isam, ike_sa_id);
140 tester->assert_true(tester, (status == SUCCESS), "delete IKE_SA by id");
141
142
143 for (i = 0; i < thread_count; i++)
144 {
145 pthread_join(threads[i], NULL);
146 }
147
148 ike_sa_id->destroy(ike_sa_id);
149
150
151 /* Second Test:
152 * now we simulate our partner initiates an IKE_SA_INIT,
153 * so we are the responder.
154 *
155 */
156 memset(&initiator, 0, sizeof(initiator));
157 memset(&responder, 0, sizeof(responder));
158
159 initiator.low = 123;
160 ike_sa_id = ike_sa_id_create(initiator, responder, RESPONDER);
161
162 status = td.isam->checkout(td.isam, ike_sa_id, &ike_sa);
163 tester->assert_true(tester, (status == SUCCESS), "checkout unexisting IKE_SA 2");
164 for (i = 0; i < thread_count; i++)
165 {
166 if (pthread_create(&threads[i], NULL, (void*(*)(void*))test2_thread, (void*)ike_sa_id))
167 {
168 /* failed, decrease list */
169 thread_count--;
170 i--;
171 }
172 }
173 /* let them go acquiring */
174 sleep(1);
175
176 /* this time, we delete the ike_sa while its checked out */
177 td.isam->checkin_and_delete(td.isam, ike_sa);
178 tester->assert_true(tester, (status == SUCCESS), "delete IKE_SA by SA");
179
180 for (i = 0; i < thread_count; i++)
181 {
182 pthread_join(threads[i], NULL);
183 }
184
185 ike_sa_id->destroy(ike_sa_id);
186
187 /* Third Test:
188 * put in a lot of IKE_SAs, check it out, set a thread waiting
189 * and destroy the manager...
190 */
191
192 memset(&initiator, 0, sizeof(initiator));
193 memset(&responder, 0, sizeof(responder));
194
195 thread_count = sa_count;
196
197 for (i = 0; i < sa_count; i++)
198 {
199 initiator.low = i + 1;
200 ike_sa_id = ike_sa_id_create(initiator, responder, RESPONDER);
201
202 status = td.isam->checkout(td.isam, ike_sa_id, &ike_sa);
203 tester->assert_true(tester, (status == SUCCESS), "checkout unexisting IKE_SA 3");
204
205 if (pthread_create(&threads[i], NULL, (void*(*)(void*))test3_thread, (void*)ike_sa_id))
206 {
207 /* failed, decrease list */
208 thread_count--;
209 }
210 }
211
212 /* let them go acquiring */
213 sleep(1);
214
215 status = td.isam->destroy(td.isam);
216 tester->assert_true(tester, (status == SUCCESS), "ike_sa_manager destruction");
217
218 for (i = 0; i < thread_count; i++)
219 {
220 pthread_join(threads[i], NULL);
221 }
222
223
224 }
225