- finish functionality of ike_sa_manager
[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 successful_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 static void failed_thread(ike_sa_id_t *ike_sa_id)
51 {
52 ike_sa_t *ike_sa;
53 status_t status;
54
55 status = td.isam->checkout(td.isam, ike_sa_id, &ike_sa);
56 td.tester->assert_true(td.tester, (status == NOT_FOUND), "IKE_SA already deleted");
57 }
58
59 void test_ike_sa_manager(tester_t *tester)
60 {
61 status_t status;
62 spi_t initiator, responder;
63 ike_sa_id_t *ike_sa_id;
64 ike_sa_t *ike_sa;
65 int thread_count = 200;
66 int sa_count = 50;
67 int i;
68 pthread_t threads[thread_count];
69
70 td.tester = tester;
71 td.isam = ike_sa_manager_create();
72
73
74
75
76
77 /* First Test:
78 * we play initiator for IKE_SA_INIT first
79 * create an IKE_SA,
80 *
81 */
82 memset(&initiator, 0, sizeof(initiator));
83 memset(&responder, 0, sizeof(responder));
84
85 ike_sa_id = ike_sa_id_create(initiator, responder, INITIATOR);
86
87 status = td.isam->checkout(td.isam, ike_sa_id, &ike_sa);
88 tester->assert_true(tester, (status == SUCCESS), "checkout unexisting IKE_SA");
89 /* for testing purposes, we manipulate the responder spi.
90 * this is usually done be the response from the communication partner,
91 * but we don't have one...
92 */
93 ike_sa_id->destroy(ike_sa_id);
94 ike_sa_id = ike_sa->get_id(ike_sa);
95 responder.low = 123;
96 ike_sa_id->set_responder_spi(ike_sa_id, responder);
97 /* check in, so we should have a "completed" sa, specified by ike_sa_id */
98 status = td.isam->checkin(td.isam, ike_sa);
99 tester->assert_true(tester, (status == SUCCESS), "checkin modified IKE_SA");
100
101 /* now we check it out and start some other threads */
102 status = td.isam->checkout(td.isam, ike_sa_id, &ike_sa);
103 tester->assert_true(tester, (status == SUCCESS), "checkout existing IKE_SA 1");
104
105
106
107 for (i = 0; i < thread_count; i++)
108 {
109 if (pthread_create(&threads[i], NULL, (void*(*)(void*))successful_thread, (void*)ike_sa_id))
110 {
111 /* failed, decrease list */
112 thread_count--;
113 i--;
114 }
115 }
116 sleep(1);
117
118 status = td.isam->checkin(td.isam, ike_sa);
119 tester->assert_true(tester, (status == SUCCESS), "checkin IKE_SA");
120
121
122 sleep(1);
123 /* we now delete the IKE_SA, while it is requested by the threads.
124 * this should block until the have done their work.*/
125 status = td.isam->delete(td.isam, ike_sa_id);
126 tester->assert_true(tester, (status == SUCCESS), "delete IKE_SA by id");
127
128
129 for (i = 0; i < thread_count; i++)
130 {
131 pthread_join(threads[i], NULL);
132 }
133
134
135
136
137
138 /* Second Test:
139 * now we simulate our partner initiates an IKE_SA_INIT,
140 * so we are the responder.
141 *
142 */
143
144 memset(&initiator, 0, sizeof(initiator));
145 memset(&responder, 0, sizeof(responder));
146
147 initiator.low = 123;
148 ike_sa_id = ike_sa_id_create(initiator, responder, RESPONDER);
149
150 status = td.isam->checkout(td.isam, ike_sa_id, &ike_sa);
151 tester->assert_true(tester, (status == SUCCESS), "checkout unexisting IKE_SA 2");
152 //ike_sa_id->destroy(ike_sa_id);
153 for (i = 0; i < thread_count; i++)
154 {
155 if (pthread_create(&threads[i], NULL, (void*(*)(void*))failed_thread, (void*)ike_sa_id))
156 {
157 /* failed, decrease list */
158 thread_count--;
159 i--;
160 }
161 }
162 /* let them go acquiring */
163 sleep(1);
164
165 /* this time, we delete the ike_sa while its checked out */
166 td.isam->checkin_and_delete(td.isam, ike_sa);
167 tester->assert_true(tester, (status == SUCCESS), "delete IKE_SA by SA");
168
169 for (i = 0; i < thread_count; i++)
170 {
171 pthread_join(threads[i], NULL);
172 }
173
174 /* Third Test:
175 * put in a lot of IKE_SAs, check it out, set a thread waiting
176 * and destroy the manager...
177 */
178
179 memset(&initiator, 0, sizeof(initiator));
180 memset(&responder, 0, sizeof(responder));
181
182 thread_count = sa_count;
183
184 for (i = 0; i < sa_count; i++)
185 {
186 initiator.low = i + 1;
187 ike_sa_id = ike_sa_id_create(initiator, responder, RESPONDER);
188
189 status = td.isam->checkout(td.isam, ike_sa_id, &ike_sa);
190 tester->assert_true(tester, (status == SUCCESS), "checkout unexisting IKE_SA 3");
191
192 if (pthread_create(&threads[i], NULL, (void*(*)(void*))failed_thread, (void*)ike_sa_id))
193 {
194 /* failed, decrease list */
195 thread_count--;
196 }
197 //ike_sa_id->destroy(ike_sa_id);
198 }
199
200 /* let them go acquiring */
201 sleep(1);
202
203 td.isam->destroy(td.isam);
204
205 for (i = 0; i < thread_count; i++)
206 {
207 pthread_join(threads[i], NULL);
208 }
209
210 }
211