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
"Welcome to our mercurial repository"