test_notifications.c revision 8a4b0b791bf38ef8389a6501a586d8ab554e3711
0N/A/**
0N/A * The contents of this file are subject to the terms of the Common Development and
0N/A * Distribution License (the License). You may not use this file except in compliance with the
0N/A * License.
0N/A *
0N/A * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
0N/A * specific language governing permission and limitations under the License.
0N/A *
0N/A * When distributing Covered Software, include this CDDL Header Notice in each file and include
0N/A * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
0N/A * Header, with the fields enclosed by brackets [] replaced by your own identifying
0N/A * information: "Portions copyright [year] [name of copyright owner]".
0N/A *
0N/A * Copyright 2014 - 2015 ForgeRock AS.
0N/A */
0N/A
0N/A#include <stdio.h>
0N/A#include <string.h>
0N/A#include <setjmp.h>
0N/A
0N/A#include "platform.h"
0N/A#include "am.h"
0N/A#include "utility.h"
0N/A#include "thread.h"
0N/A#include "cmocka.h"
0N/A
0N/Atypedef am_return_t (* am_state_func_t)(am_request_t *);
0N/A
0N/Avoid am_test_get_state_funcs(am_state_func_t const ** func_array_p, int * func_array_len_p);
0N/A
0N/Avoid am_worker_pool_init_reset();
0N/Avoid am_net_init_ssl_reset();
0N/A
0N/Astatic am_status_t get_post_data(struct am_request * request)
0N/A{
0N/A return AM_SUCCESS;
0N/A}
0N/A
0N/Astatic am_status_t set_custom_response(struct am_request * request, const char * data, const char * content_type)
0N/A{
0N/A return AM_SUCCESS;
0N/A}
0N/A
0N/A
0N/Avoid test_simple_fail(void **state) {
0N/A
0N/A am_state_func_t const * func_array = NULL;
0N/A int array_len = 0;
0N/A am_state_func_t notification_handler;
0N/A
0N/A char * post_data =
0N/A "<NotificationSet version='1.0'>"
0N/A " <Notification>"
0N/A //option - invalidate config changed ( not for specific instance )
0N/A //" <AgentConfigChangeNotification />"
0N/A //option - invalidate session by sid ( state must be present, not is not used )
0N/A //" <SessionNotification>"
0N/A //" <Session sid='my-session' state='destroyed' />"
0N/A //" </SessionNotification>"
0N/A //option remove specific resources from the cache - check that it is the right service
0N/A //these can't be removed by resource from the session cache
0N/A " <PolicyChangeNotification serviceName='identified-service' >"
0N/A " <ResourceName type='added' >a.b.c:3232/d/e/f</ResourceName>"
0N/A " <ResourceName type='deleted' >a.b.c:3232/d/e/f</ResourceName>"
0N/A " <ResourceName type='modified' >a.b.c:3232/d/e/f</ResourceName>"
0N/A " </PolicyChangeNotification>"
0N/A " </Notification>"
0N/A "</NotificationSet>";
0N/A
0N/A struct ctx {
0N/A void *dummy;
0N/A } ctx;
0N/A
0N/A am_config_t config = {
0N/A .instance_id = 0,
0N/A .notif_enable = AM_TRUE,
0N/A .notif_url = "https://www.notify.com:1234/am",
0N/A .override_notif_url = AM_TRUE,
0N/A
0N/A .url_eval_case_ignore = AM_FALSE,
0N/A };
0N/A
0N/A am_request_t request = {
0N/A .instance_id = 0,
0N/A .conf = &config,
0N/A .ctx = &ctx,
0N/A
0N/A .method = AM_REQUEST_POST,
0N/A .token = NULL,
0N/A
0N/A .overridden_url = "https://www.override.com:90/am",
0N/A .normalized_url = "https://www.notify.com:90/am",
0N/A
0N/A .post_data = post_data,
0N/A .post_data_sz = strlen(post_data),
0N/A
0N/A .am_get_post_data_f = get_post_data,
0N/A
0N/A .am_set_custom_response_f = set_custom_response,
0N/A };
0N/A
0N/A am_test_get_state_funcs(&func_array, &array_len);
0N/A notification_handler = func_array[2];
0N/A
0N/A /* this is not a notification */
0N/A assert_int_equal(notification_handler(&request), AM_FAIL);
0N/A}
0N/A
0N/A
0N/Avoid test_simple_notification(void **state) {
0N/A
0N/A am_state_func_t const * func_array = NULL;
0N/A int array_len = 0;
0N/A am_state_func_t notification_handler;
0N/A
0N/A char * post_data =
0N/A "<NotificationSet version='1.0'>"
0N/A " <Notification>"
0N/A //option - invalidate config changed ( not for specific instance )
0N/A //" <AgentConfigChangeNotification />"
0N/A //option - invalidate session by sid ( state must be present, not is not used )
0N/A //" <SessionNotification>"
0N/A //" <Session sid='my-session' state='destroyed' />"
0N/A //" </SessionNotification>"
0N/A //option remove specific resources from the cache - check that it is the right service
0N/A //these can't be removed by resource from the session cache
0N/A " <PolicyChangeNotification serviceName='identified-service' >"
0N/A " <ResourceName type='added' >a.b.c:3232/d/e/f</ResourceName>"
0N/A " <ResourceName type='deleted' >a.b.c:3232/d/e/f</ResourceName>"
0N/A " <ResourceName type='modified' >a.b.c:3232/d/e/f</ResourceName>"
0N/A " </PolicyChangeNotification>"
0N/A " </Notification>"
0N/A "</NotificationSet>";
0N/A
0N/A struct ctx {
0N/A void *dummy;
0N/A } ctx;
0N/A
0N/A am_config_t config = {
0N/A .instance_id = 0,
0N/A .notif_enable = AM_TRUE,
0N/A .notif_url = "https://www.notify.com:1234/am",
0N/A .override_notif_url = AM_FALSE,
0N/A
0N/A .url_eval_case_ignore = AM_FALSE,
0N/A };
0N/A
0N/A am_request_t request = {
0N/A .instance_id = 0,
0N/A .conf = &config,
0N/A .ctx = &ctx,
0N/A
0N/A .method = AM_REQUEST_POST,
0N/A .token = NULL,
0N/A
0N/A .overridden_url = "https://www.override.com:90/am",
0N/A .normalized_url = "https://www.notify.com:1234/am",
0N/A
0N/A .post_data = post_data,
0N/A .post_data_sz = strlen(post_data),
0N/A
0N/A .am_get_post_data_f = get_post_data,
0N/A
0N/A .am_set_custom_response_f = set_custom_response,
0N/A };
0N/A
0N/A am_test_get_state_funcs(&func_array, &array_len);
0N/A notification_handler = func_array[2];
0N/A
0N/A assert_int_equal(am_init(AM_DEFAULT_AGENT_ID), AM_SUCCESS);
0N/A am_init_worker(AM_DEFAULT_AGENT_ID);
0N/A
0N/A sleep(2); /* must wait till worker pool is all set */
0N/A
0N/A /* this is a notification */
0N/A assert_int_equal(notification_handler(&request), AM_OK);
0N/A
0N/A sleep(2);
0N/A
0N/A am_shutdown_worker();
0N/A am_shutdown(AM_DEFAULT_AGENT_ID);
0N/A am_worker_pool_init_reset();
0N/A am_net_init_ssl_reset();
0N/A}
0N/A
0N/A
0N/Avoid test_session_notification_on_policy_cache(void **state) {
0N/A
0N/A const char * session_id = "XXX";
0N/A
0N/A char * session_notification =
0N/A "<NotificationSet version='1.0'>"
0N/A " <Notification>"
0N/A " <SessionNotification> <Session sid='XXX' state='destroyed' /> </SessionNotification>"
0N/A " </Notification>"
0N/A "</NotificationSet>";
0N/A
0N/A am_state_func_t const * func_array = NULL;
0N/A int array_len = 0;
0N/A am_state_func_t notification_handler;
0N/A
0N/A struct ctx {
0N/A void *dummy;
0N/A } ctx;
0N/A
0N/A am_config_t config = {
0N/A .instance_id = 0,
0N/A .token_cache_valid = 0,
0N/A
0N/A .notif_enable = AM_TRUE,
0N/A .notif_url = "https://www.notify.com:1234/am",
0N/A .override_notif_url = AM_FALSE,
0N/A
0N/A .url_eval_case_ignore = AM_FALSE,
0N/A };
0N/A
0N/A am_request_t request = {
0N/A .instance_id = 0,
0N/A .conf = &config,
0N/A .ctx = &ctx,
0N/A
0N/A .method = AM_REQUEST_POST,
0N/A .token = NULL,
0N/A
0N/A .overridden_url = "https://www.override.com:90/am",
0N/A .normalized_url = "https://www.notify.com:1234/am",
0N/A
0N/A .post_data = session_notification,
0N/A .post_data_sz = strlen(session_notification),
0N/A
0N/A .am_get_post_data_f = get_post_data,
0N/A
0N/A .am_set_custom_response_f = set_custom_response,
0N/A };
0N/A
0N/A char * xml =
0N/A "<PolicyService version='1.0' revisionNumber='60'>"
0N/A " <PolicyResponse requestId='4' issueInstant='1424783306343' >"
0N/A
0N/A " <ResourceResult name='http://vb2.local.com:80/testwebsite'>"
0N/A " <PolicyDecision>"
0N/A
0N/A " <ResponseAttributes>"
0N/A " <!-- these can have multiple (0..n) value elements -->"
0N/A " <AttributeValuePair>"
0N/A " <Attribute name='Attributes,key:0,0'/> <Value>Attributes,value:0,0,0</Value> <Value>Attributes,value:0,0,1</Value>"
0N/A " </AttributeValuePair>"
0N/A " <AttributeValuePair>"
0N/A " <Attribute name='Attributes,key:0,1'/> <Value>Attributes,value:0,1,0</Value>"
0N/A " </AttributeValuePair>"
0N/A " </ResponseAttributes>"
0N/A
0N/A " <ActionDecision timeToLive='1234'>"
0N/A " <!-- these can have no value elements, which defaults to ? -->"
0N/A " <AttributeValuePair>"
0N/A " <Attribute name='PUT'/> <Value>deny</Value>"
0N/A " </AttributeValuePair>"
0N/A " <Advices>"
0N/A " <AttributeValuePair>"
0N/A " <Attribute name='Advices,key:0,0'/> <Value>Advices,value:0,0,0</Value>"
0N/A " </AttributeValuePair>"
0N/A " <AttributeValuePair>"
0N/A " <Attribute name='Advices,key:0,1'/> <Value>Advices,value:0,1,0</Value>"
0N/A " </AttributeValuePair>"
0N/A " </Advices>"
0N/A " </ActionDecision>"
0N/A
0N/A " <ResponseDecisions>"
0N/A " <AttributeValuePair>"
0N/A " <Attribute name='Decision,key:0,0'/> <Value>Decision,value:0,0,0</Value>"
0N/A " </AttributeValuePair>"
0N/A " <AttributeValuePair>"
0N/A " <Attribute name='Decision,key:0,1'/> <Value>Decision,value:0,1,0</Value>"
0N/A " </AttributeValuePair>"
0N/A " <AttributeValuePair>"
0N/A " <Attribute name='Decision,key:0,2'/> <Value>Decision,value:0,2,0</Value>"
0N/A " </AttributeValuePair>"
0N/A " </ResponseDecisions>"
0N/A
0N/A " </PolicyDecision>"
0N/A " </ResourceResult>"
0N/A " </PolicyResponse>"
0N/A "</PolicyService>";
0N/A
0N/A char* pll = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>"
0N/A "<ResponseSet vers='1.0' svcid='poicy' reqid='48'>"
0N/A " <Response><![CDATA[%s]]></Response>"
0N/A "</ResponseSet>";
0N/A
0N/A char * buffer = NULL;
0N/A struct am_policy_result * result;
0N/A time_t ets;
0N/A struct am_policy_result * r = NULL;
0N/A struct am_namevalue * session = NULL;
0N/A
0N/A am_asprintf(&buffer, pll, xml);
0N/A
0N/A result = am_parse_policy_xml(0l, buffer, strlen(buffer), 0);
0N/A
0N/A free(buffer);
0N/A
0N/A am_test_get_state_funcs(&func_array, &array_len);
0N/A notification_handler = func_array [2];
0N/A
0N/A assert_int_equal(am_init(AM_DEFAULT_AGENT_ID), AM_SUCCESS);
0N/A am_init_worker(AM_DEFAULT_AGENT_ID);
0N/A
0N/A sleep(2); /* must wait till worker pool is all set */
0N/A
0N/A assert_int_equal(am_add_session_policy_cache_entry(&request, session_id, result, NULL), AM_SUCCESS);
0N/A
0N/A delete_am_policy_result_list(&result);
0N/A
0N/A /* find the session */
0N/A assert_int_equal(am_get_session_policy_cache_entry(&request, session_id, &r, &session, &ets), AM_SUCCESS);
0N/A delete_am_policy_result_list(&r);
0N/A
0N/A /* this is a notification */
0N/A assert_int_equal(notification_handler(&request), AM_OK);
0N/A
0N/A /* wait for the worker to have finished */
0N/A sleep(2);
0N/A
0N/A assert_int_equal(am_get_session_policy_cache_entry(&request, session_id, &r, &session, &ets), AM_NOT_FOUND);
0N/A
0N/A am_shutdown_worker();
0N/A am_shutdown(AM_DEFAULT_AGENT_ID);
0N/A am_worker_pool_init_reset();
0N/A am_net_init_ssl_reset();
0N/A}
0N/A
0N/A
0N/A
0N/Avoid test_resource_notification_on_policy_cache(void **state) {
0N/A
0N/A am_state_func_t const * func_array = NULL;
0N/A int array_len = 0;
0N/A am_state_func_t notification_handler;
0N/A
0N/A struct ctx {
0N/A void *dummy;
0N/A } ctx;
0N/A
0N/A const char * session_id = "XXX";
0N/A
0N/A char * session_notification =
0N/A "<NotificationSet version='1.0'>"
0N/A " <Notification>"
0N/A " <PolicyChangeNotification serviceName='identified-service' >"
0N/A " <ResourceName type='deleted' >a.b.c:3232/d/e/f</ResourceName>"
0N/A " <ResourceName type='modified' >a.b.c:3232/d/e/f</ResourceName>"
0N/A " </PolicyChangeNotification>"
0N/A " </Notification>"
0N/A "</NotificationSet>";
0N/A
0N/A am_config_t config = {
0N/A .instance_id = 0,
0N/A .token_cache_valid = 0,
0N/A
0N/A .notif_enable = AM_TRUE,
0N/A .notif_url = "https://www.notify.com:1234/am",
0N/A .override_notif_url = AM_FALSE,
0N/A
0N/A .url_eval_case_ignore = AM_FALSE,
0N/A };
0N/A
0N/A am_request_t request = {
0N/A .instance_id = 0,
0N/A .conf = &config,
0N/A .ctx = &ctx,
0N/A
.method = AM_REQUEST_POST,
.token = NULL,
.overridden_url = "https://www.override.com:90/am",
.normalized_url = "https://www.notify.com:1234/am",
.post_data = session_notification,
.post_data_sz = strlen(session_notification),
.am_get_post_data_f = get_post_data,
.am_set_custom_response_f = set_custom_response,
};
char * xml =
"<PolicyService version='1.0' revisionNumber='60'>"
" <PolicyResponse requestId='4' issueInstant='1424783306343' >"
" <ResourceResult name='a.b.c:3232/d/e/f'>"
" <PolicyDecision>"
" <ResponseAttributes>"
" <!-- these can have multiple (0..n) value elements -->"
" <AttributeValuePair>"
" <Attribute name='Attributes,key:0,0'/> <Value>Attributes,value:0,0,0</Value> <Value>Attributes,value:0,0,1</Value>"
" </AttributeValuePair>"
" <AttributeValuePair>"
" <Attribute name='Attributes,key:0,1'/> <Value>Attributes,value:0,1,0</Value>"
" </AttributeValuePair>"
" </ResponseAttributes>"
" <ActionDecision timeToLive='1234'>"
" <!-- these can have no value elements, which defaults to ? -->"
" <AttributeValuePair>"
" <Attribute name='PUT'/> <Value>deny</Value>"
" </AttributeValuePair>"
" <Advices>"
" <AttributeValuePair>"
" <Attribute name='Advices,key:0,0'/> <Value>Advices,value:0,0,0</Value>"
" </AttributeValuePair>"
" <AttributeValuePair>"
" <Attribute name='Advices,key:0,1'/> <Value>Advices,value:0,1,0</Value>"
" </AttributeValuePair>"
" </Advices>"
" </ActionDecision>"
" <ResponseDecisions>"
" <AttributeValuePair>"
" <Attribute name='Decision,key:0,0'/> <Value>Decision,value:0,0,0</Value>"
" </AttributeValuePair>"
" <AttributeValuePair>"
" <Attribute name='Decision,key:0,1'/> <Value>Decision,value:0,1,0</Value>"
" </AttributeValuePair>"
" <AttributeValuePair>"
" <Attribute name='Decision,key:0,2'/> <Value>Decision,value:0,2,0</Value>"
" </AttributeValuePair>"
" </ResponseDecisions>"
" </PolicyDecision>"
" </ResourceResult>"
" </PolicyResponse>"
"</PolicyService>";
char * pll = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>"
"<ResponseSet vers='1.0' svcid='poicy' reqid='48'>"
" <Response><![CDATA[%s]]></Response>"
"</ResponseSet>";
char * buffer = NULL;
/* when the worker has finished, the session result list should be unchanged, but policy cache entry removed */
time_t ets;
struct am_policy_result * r = NULL;
struct am_namevalue * session = NULL;
struct am_policy_result * p;
struct am_policy_result * result;
am_asprintf(&buffer, pll, xml);
result = am_parse_policy_xml(0l, buffer, strlen(buffer), 0);
free(buffer);
am_test_get_state_funcs(&func_array, &array_len);
notification_handler = func_array [2];
assert_int_equal(am_init(AM_DEFAULT_AGENT_ID), AM_SUCCESS);
am_init_worker(AM_DEFAULT_AGENT_ID);
sleep(2); /* must wait till worker pool is all set */
assert_int_equal(am_add_session_policy_cache_entry(&request, session_id, result, 0), AM_SUCCESS);
/* add the resources to the policy cache */
for(p = result; p; p = p->next) {
am_add_policy_cache_entry(&request, p->resource, 500);
}
delete_am_policy_result_list(&result);
/* send a resource notification for the cached resource */
assert_int_equal(notification_handler(&request), AM_OK);
sleep(2);
assert_int_equal(am_get_session_policy_cache_entry(&request, session_id, &r, &session, &ets), AM_SUCCESS);
if (r != NULL) {
assert_int_equal(strcmp(r->resource, "a.b.c:3232/d/e/f"), 0);
assert_int_equal(am_get_policy_cache_entry(&request, r->resource, 0), AM_NOT_FOUND);
}
delete_am_policy_result_list(&r);
am_shutdown_worker();
am_shutdown(AM_DEFAULT_AGENT_ID);
am_worker_pool_init_reset();
am_net_init_ssl_reset();
}