2 * Copyright (c) 2017, JANET(UK)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of JANET(UK) nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 * OF THE POSSIBILITY OF SUCH DAMAGE.
41 #include <trp_internal.h>
42 #include <tid_internal.h>
43 #include <tr_filter.h>
44 #include <tr_config.h>
46 #define FILTER_PATH "./test-filters/"
49 * Load a JSON file containing filters and return the filters from the first rp_client.
51 * @param fname File to read
52 * @param filt_out Will point to the loaded filter on success
53 * @return Return value from tr_cfg_parse_one_config_file()
55 int load_filter(const char *fname, TR_FILTER_SET **filts_out)
57 TR_CFG *cfg=tr_cfg_new(NULL);
58 TR_CFG_RC rc=TR_CFG_ERROR;
63 rc=tr_cfg_parse_one_config_file(cfg, fname);
64 if (rc!=TR_CFG_SUCCESS)
67 /* Steal the filter from the first rp_client */
69 assert(cfg->rp_clients);
70 assert(cfg->rp_clients->filters);
71 *filts_out=cfg->rp_clients->filters;
72 cfg->rp_clients->filters=NULL; /* can't use the _set_filter() because that will free the filter */
73 talloc_steal(NULL, *filts_out);
81 * Test that filters load / fail to load as expected.
83 * @return 1 if all tests pass
85 int test_load_filter(void)
87 TR_FILTER_SET *filts=NULL;
89 assert(TR_CFG_SUCCESS==load_filter(FILTER_PATH "valid-filt.json", &filts));
90 if (filts) tr_filter_set_free(filts);
92 assert(TR_CFG_NOPARSE==load_filter(FILTER_PATH "invalid-filt-repeated-key.json", &filts));
93 if (filts) tr_filter_set_free(filts);
95 assert(TR_CFG_ERROR==load_filter(FILTER_PATH "invalid-filt-unknown-field.json", &filts));
96 if (filts) tr_filter_set_free(filts);
102 * Read the first inforec from the TR_MSG encoded in JSON file named fname.
104 * @param fname Filename with path for TR_MSG JSON
105 * @return Pointer to the decoded inforec, or NULL on failure
107 TRP_INFOREC *load_inforec(const char *fname)
111 TRP_INFOREC *inforec=NULL;
112 json_t *decoded=json_load_file(fname, JSON_REJECT_DUPLICATES|JSON_DISABLE_EOF_CHECK, NULL);
113 char *encoded=json_dumps(decoded, 0); /* silly way to read the file without mucking around */
116 json_decref(decoded);
119 assert(msg=tr_msg_decode(encoded, strlen(encoded)));
120 assert(upd=tr_msg_get_trp_upd(msg));
121 assert(inforec=trp_upd_get_inforec(upd));
122 /* now remove the inforec from the update context */
123 talloc_steal(NULL, inforec);
124 tr_msg_free_decoded(msg);
125 tr_msg_free_encoded(encoded);
129 /* make this bigger than your message file */
130 #define MAX_FILE_SIZE 20000
131 TID_REQ *load_tid_req(const char *fname)
139 msgbuf=malloc(MAX_FILE_SIZE);
143 msglen=fread(msgbuf, 1, MAX_FILE_SIZE, f);
146 msg=tr_msg_decode(msgbuf, msglen);
151 assert(tr_msg_get_msg_type(msg)==TID_REQUEST);
153 /* take the tid req out of the msg */
154 out=tr_msg_get_req(msg);
155 tr_msg_set_req(msg, NULL);
158 tr_msg_free_decoded(msg);
163 * Read a set of filters from a config JSON in filt_fname and test against the tid_req or inforec in target_fname.
164 * If expect==1, succeed if the target is accepted by the filter, otherwise succeed if it is rejected.
165 * Takes filters from the first rp_realm defined in the filter file and the first inforec or tid req from
168 * @param filt_fname Name of JSON file containing filters
169 * @param ftype Which type of filter to test
170 * @param target_fname Name of JSON file containing inforec
171 * @param expected_match 1 if we expect a match, 0 otherwise
172 * @param expected_action Expected action if the filter matches
173 * @return 1 if expected result is obtained, 0 or does not return otherwise
175 int test_one_filter(const char *filt_fname,
176 TR_FILTER_TYPE ftype,
177 const char *target_fname,
179 TR_FILTER_ACTION expected_action)
182 TR_FILTER_SET *filts=NULL;
183 TR_FILTER_ACTION action=TR_FILTER_ACTION_UNKNOWN;
185 /* load filter for first test */
186 assert(TR_CFG_SUCCESS==load_filter(filt_fname, &filts));
188 /* load the target req or inforec */
190 case TR_FILTER_TYPE_TID_INBOUND:
191 target=load_tid_req(target_fname);
194 case TR_FILTER_TYPE_TRP_INBOUND:
195 case TR_FILTER_TYPE_TRP_OUTBOUND:
196 target=load_inforec(target_fname);
200 printf("Unknown filter type.\n");
204 assert(expected_match==tr_filter_apply(target, tr_filter_set_get(filts, ftype), NULL, &action));
205 if (expected_match==TR_FILTER_MATCH)
206 assert(action==expected_action);
208 tr_filter_set_free(filts);
210 case TR_FILTER_TYPE_TID_INBOUND:
211 tid_req_free((TID_REQ *)target);
214 case TR_FILTER_TYPE_TRP_INBOUND:
215 case TR_FILTER_TYPE_TRP_OUTBOUND:
216 trp_inforec_free((TRP_INFOREC *)target);
220 printf("Unknown filter type.\n");
225 int test_filter(void)
227 json_t *test_list=json_load_file(FILTER_PATH "filter-tests.json", JSON_DISABLE_EOF_CHECK, NULL);
230 const char *filt_file, *target_file;
231 TR_FILTER_TYPE ftype;
233 TR_FILTER_ACTION action;
235 json_array_foreach(test_list, ii, this) {
236 printf("Running filter test case: %s\n", json_string_value(json_object_get(this, "test label")));
239 filt_file=json_string_value(json_object_get(this, "filter file"));
240 ftype=tr_filter_type_from_string(json_string_value(json_object_get(this, "filter type")));
241 target_file=json_string_value(json_object_get(this, "target file"));
242 if (0==strcmp("yes", json_string_value(json_object_get(this, "expect match"))))
243 expect_match=TR_FILTER_MATCH;
245 expect_match=TR_FILTER_NO_MATCH;
247 if (0==strcmp("accept", json_string_value(json_object_get(this, "action"))))
248 action=TR_FILTER_ACTION_ACCEPT;
250 action=TR_FILTER_ACTION_REJECT;
252 assert(test_one_filter(filt_file, ftype, target_file, expect_match, action));
262 assert(test_load_filter());
263 assert(test_filter());