Mercurial > hg > freeDiameter
comparison freeDiameter/tests/testappacct.c @ 285:0daf6fc2b751
Added a test case for the app_acct extension
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Fri, 30 Apr 2010 17:55:16 +0900 |
parents | |
children | 9d786d459dc8 |
comparison
equal
deleted
inserted
replaced
284:397cdcd41f53 | 285:0daf6fc2b751 |
---|---|
1 /********************************************************************************************************* | |
2 * Software License Agreement (BSD License) * | |
3 * Author: Sebastien Decugis <sdecugis@nict.go.jp> * | |
4 * * | |
5 * Copyright (c) 2009, WIDE Project and NICT * | |
6 * All rights reserved. * | |
7 * * | |
8 * Redistribution and use of this software in source and binary forms, with or without modification, are * | |
9 * permitted provided that the following conditions are met: * | |
10 * * | |
11 * * Redistributions of source code must retain the above * | |
12 * copyright notice, this list of conditions and the * | |
13 * following disclaimer. * | |
14 * * | |
15 * * Redistributions in binary form must reproduce the above * | |
16 * copyright notice, this list of conditions and the * | |
17 * following disclaimer in the documentation and/or other * | |
18 * materials provided with the distribution. * | |
19 * * | |
20 * * Neither the name of the WIDE Project or NICT nor the * | |
21 * names of its contributors may be used to endorse or * | |
22 * promote products derived from this software without * | |
23 * specific prior written permission of WIDE Project and * | |
24 * NICT. * | |
25 * * | |
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * | |
27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * | |
28 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * | |
29 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * | |
30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * | |
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * | |
32 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * | |
33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * | |
34 *********************************************************************************************************/ | |
35 | |
36 #include "tests.h" | |
37 | |
38 /* The connection string to the database */ | |
39 #ifndef TEST_CONNINFO | |
40 #error "Please specify the conninfo information" | |
41 #endif /* TEST_CONNINFO */ | |
42 | |
43 /* The table used for tests. This table will receive the following instructions: | |
44 DROP TABLE <table>; | |
45 CREATE TABLE <table> | |
46 ( | |
47 ts timestamp with time zone NOT NULL, | |
48 "Accounting-Record-Type" integer, | |
49 "Session-Id" bytea, | |
50 "Accounting-Record-Number" integer, | |
51 "Route-Record1" bytea, | |
52 "Route-Record2" bytea, | |
53 "Route-Record3" bytea, | |
54 "Route-Record4" bytea | |
55 ); | |
56 */ | |
57 #define TABLE "incoming_test" | |
58 | |
59 #include "app_acct.h" | |
60 #include <libpq-fe.h> | |
61 | |
62 static int add_avp_in_conf(char * avpname, int multi) | |
63 { | |
64 struct acct_conf_avp *new; | |
65 struct dict_object * dict; | |
66 struct dict_avp_data dictdata; | |
67 | |
68 /* Validate the avp name first */ | |
69 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, avpname, &dict, ENOENT) ); | |
70 CHECK_FCT( fd_dict_getval( dict, &dictdata )); | |
71 | |
72 /* Create a new entry */ | |
73 CHECK_MALLOC( new = malloc(sizeof(struct acct_conf_avp)) ); | |
74 memset(new, 0, sizeof(struct acct_conf_avp)); | |
75 fd_list_init(&new->chain, NULL); | |
76 new->avpname = avpname; | |
77 new->avpobj = dict; | |
78 new->avptype = dictdata.avp_basetype; | |
79 new->multi = multi; | |
80 | |
81 /* Add this new entry at the end of the list */ | |
82 fd_list_insert_before( &acct_config->avps, &new->chain ); | |
83 | |
84 return 0; | |
85 } | |
86 | |
87 /* Main test routine */ | |
88 int main(int argc, char *argv[]) | |
89 { | |
90 extern PGconn *conn; /* in acct_db.c */ | |
91 struct msg * msg; | |
92 char * sess_bkp; | |
93 struct dict_object * session_id = NULL; | |
94 | |
95 /* First, initialize the daemon modules */ | |
96 INIT_FD(); | |
97 fd_g_config->cnf_diamid = strdup("test.app.acct"); | |
98 fd_g_config->cnf_diamid_len = strlen(fd_g_config->cnf_diamid); | |
99 fd_g_config->cnf_diamrlm = strdup("app.acct"); | |
100 fd_g_config->cnf_diamrlm_len = strlen(fd_g_config->cnf_diamrlm); | |
101 | |
102 CHECK( 0, fd_queues_init() ); | |
103 CHECK( 0, fd_msg_init() ); | |
104 CHECK( 0, fd_rtdisp_init() ); | |
105 | |
106 /* Initialize the extension configuration for the test */ | |
107 { | |
108 CHECK( 0, acct_conf_init() ); | |
109 acct_config->conninfo = strdup(TEST_CONNINFO); | |
110 acct_config->tablename = strdup(TABLE); | |
111 acct_config->tsfield = strdup("ts"); | |
112 CHECK( 0, add_avp_in_conf(strdup("Session-Id"), 0) ); | |
113 CHECK( 0, add_avp_in_conf(strdup("Accounting-Record-Type"), 0) ); | |
114 CHECK( 0, add_avp_in_conf(strdup("Accounting-Record-Number"), 0) ); | |
115 CHECK( 0, add_avp_in_conf(strdup("Route-Record"), 4) ); | |
116 | |
117 /* Now, call the one of the extension */ | |
118 CHECK( 0, fd_ext_init(FD_PROJECT_VERSION_MAJOR, FD_PROJECT_VERSION_MINOR,NULL) ); | |
119 } | |
120 | |
121 /* Drop and recreate the table for the test */ | |
122 { | |
123 PGresult * res; | |
124 CHECK( CONNECTION_OK, PQstatus(conn) ); | |
125 | |
126 res = PQexec(conn, "DROP TABLE " TABLE ";"); | |
127 CHECK( PGRES_COMMAND_OK, PQresultStatus(res) ); | |
128 PQclear(res); | |
129 | |
130 res = PQexec(conn, "CREATE TABLE " TABLE " ( " | |
131 " ts timestamp with time zone NOT NULL, " | |
132 " \"Accounting-Record-Type\" integer, " | |
133 " \"Session-Id\" bytea, " | |
134 " \"Accounting-Record-Number\" integer, " | |
135 " \"Route-Record1\" bytea, " | |
136 " \"Route-Record2\" bytea, " | |
137 " \"Route-Record3\" bytea, " | |
138 " \"Route-Record4\" bytea " | |
139 ");" | |
140 ); | |
141 CHECK( PGRES_COMMAND_OK, PQresultStatus(res) ); | |
142 PQclear(res); | |
143 } | |
144 | |
145 /* OK, we are ready to test now. Create an ACR message that will pass the ABNF check */ | |
146 { | |
147 struct dict_object * d = NULL; | |
148 struct avp *avp = NULL; | |
149 union avp_value avp_val; | |
150 | |
151 /* Now find the ACR dictionary object */ | |
152 CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &d, ENOENT ) ); | |
153 | |
154 /* Create the instance */ | |
155 CHECK( 0, fd_msg_new ( d, MSGFL_ALLOC_ETEID, &msg ) ); | |
156 | |
157 /* App id */ | |
158 { | |
159 struct msg_hdr * h; | |
160 CHECK( 0, fd_msg_hdr( msg, &h ) ); | |
161 h->msg_appl = 3; | |
162 } | |
163 | |
164 /* sid */ | |
165 { | |
166 struct session * sess = NULL; | |
167 char * s; | |
168 CHECK( 0, fd_sess_new( &sess, fd_g_config->cnf_diamid, NULL, 0) ); | |
169 CHECK( 0, fd_sess_getsid(sess, &s) ); | |
170 sess_bkp = strdup(s); | |
171 | |
172 CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &d, ENOENT ) ); | |
173 CHECK( 0, fd_msg_avp_new ( d, 0, &avp ) ); | |
174 memset(&avp_val, 0, sizeof(avp_val)); | |
175 avp_val.os.data = (unsigned char *)sess_bkp; | |
176 avp_val.os.len = strlen(sess_bkp); | |
177 CHECK( 0, fd_msg_avp_setvalue ( avp, &avp_val ) ); | |
178 CHECK( 0, fd_msg_avp_add ( msg, MSG_BRW_FIRST_CHILD, avp) ); | |
179 } | |
180 | |
181 /* Origin-* */ | |
182 CHECK( 0, fd_msg_add_origin(msg, 1) ); | |
183 | |
184 /* Destination-Realm */ | |
185 { | |
186 CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Realm", &d, ENOENT ) ); | |
187 CHECK( 0, fd_msg_avp_new ( d, 0, &avp ) ); | |
188 memset(&avp_val, 0, sizeof(avp_val)); | |
189 avp_val.os.data = (unsigned char *)fd_g_config->cnf_diamrlm; | |
190 avp_val.os.len = fd_g_config->cnf_diamrlm_len; | |
191 CHECK( 0, fd_msg_avp_setvalue ( avp, &avp_val ) ); | |
192 CHECK( 0, fd_msg_avp_add ( msg, MSG_BRW_LAST_CHILD, avp) ); | |
193 } | |
194 | |
195 /* Accounting-Record-Type */ | |
196 { | |
197 CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Record-Type", &d, ENOENT ) ); | |
198 CHECK( 0, fd_msg_avp_new ( d, 0, &avp ) ); | |
199 memset(&avp_val, 0, sizeof(avp_val)); | |
200 avp_val.u32 = 2; | |
201 CHECK( 0, fd_msg_avp_setvalue ( avp, &avp_val ) ); | |
202 CHECK( 0, fd_msg_avp_add ( msg, MSG_BRW_LAST_CHILD, avp) ); | |
203 } | |
204 | |
205 /* Accounting-Record-Number */ | |
206 { | |
207 CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Record-Number", &d, ENOENT ) ); | |
208 CHECK( 0, fd_msg_avp_new ( d, 0, &avp ) ); | |
209 memset(&avp_val, 0, sizeof(avp_val)); | |
210 avp_val.u32 = 2; | |
211 CHECK( 0, fd_msg_avp_setvalue ( avp, &avp_val ) ); | |
212 CHECK( 0, fd_msg_avp_add ( msg, MSG_BRW_LAST_CHILD, avp) ); | |
213 } | |
214 | |
215 /* Route-Record */ | |
216 { | |
217 CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Route-Record", &d, ENOENT ) ); | |
218 CHECK( 0, fd_msg_avp_new ( d, 0, &avp ) ); | |
219 memset(&avp_val, 0, sizeof(avp_val)); | |
220 avp_val.os.data = (unsigned char *)"peer1"; | |
221 avp_val.os.len = strlen((char *)avp_val.os.data); | |
222 CHECK( 0, fd_msg_avp_setvalue ( avp, &avp_val ) ); | |
223 CHECK( 0, fd_msg_avp_add ( msg, MSG_BRW_LAST_CHILD, avp) ); | |
224 | |
225 CHECK( 0, fd_msg_avp_new ( d, 0, &avp ) ); | |
226 memset(&avp_val, 0, sizeof(avp_val)); | |
227 avp_val.os.data = (unsigned char *)"peer2"; | |
228 avp_val.os.len = strlen((char *)avp_val.os.data); | |
229 CHECK( 0, fd_msg_avp_setvalue ( avp, &avp_val ) ); | |
230 CHECK( 0, fd_msg_avp_add ( msg, MSG_BRW_LAST_CHILD, avp) ); | |
231 } | |
232 | |
233 /* Source */ | |
234 CHECK( 0, fd_msg_source_set( msg, "peer3", 1, fd_g_config->cnf_dict ) ); | |
235 } | |
236 | |
237 /* Now, have the daemon handle this */ | |
238 CHECK( 0, fd_fifo_post(fd_g_incoming, &msg) ); | |
239 | |
240 /* It is picked by the dispatch module, the extension handles the query, inserts the records in the DB, send creates the answer. | |
241 Once the answer is ready, it is sent to "peer3" which is not available of course; then the message is simply destroyed. | |
242 We wait 1 second for this to happen... */ | |
243 sleep(1); | |
244 | |
245 /* Now, check the record was actually registered properly */ | |
246 { | |
247 PGresult * res; | |
248 char * s; | |
249 res = PQexec(conn, "SELECT \"Session-Id\" from " TABLE ";"); | |
250 CHECK( PGRES_TUPLES_OK, PQresultStatus(res) ); | |
251 | |
252 /* We also check that the Session-Id we retrieve is the same as what we generated earlier (not trashed in the process) */ | |
253 s = PQgetvalue(res, 0, 0); | |
254 CHECK( 0, strcmp(s, sess_bkp) ); | |
255 | |
256 PQclear(res); | |
257 } | |
258 | |
259 /* That's all for the tests yet */ | |
260 free(sess_bkp); | |
261 fd_ext_fini(); | |
262 | |
263 PASSTEST(); | |
264 } | |
265 |